How Lego‑Style Page Structuring Transforms Android MVP Development
This article explores how applying a Lego‑like page‑structuring approach to Android MVP can improve decoupling, reduce method count, and enhance maintainability, while comparing its benefits and drawbacks against traditional MVP implementations.
MVP Overview
MVP is a design pattern that separates UI logic from business logic in Android, addressing the shortcomings of MVC where Activity often mixes responsibilities. The core idea is that the View does not interact directly with the Model.
MVP abstracts the UI logic in an Activity into a View interface, the business logic into a Presenter interface, while the Model class remains unchanged.
View : Implemented by the Activity and responds to lifecycle events.
Model : The data layer, including network, cache, and parsing.
Presenter : Mediates between View and Model; the View must interact with the Model through the Presenter.
View interface : Defines the methods the View must implement to communicate with the Presenter, reducing coupling.
Practical MVP Application in Riji
View Interface
public interface IMyStoryListView {
public void setData(MyStorys myStoryList, RecentStory recentStoryList);
public void setSegmentData(String key, Object data, boolean needRefreshUi);
/**
* Callback after data update to refresh UI
*/
public void pullRefreshCompleted(boolean success, boolean isReqCompleted);
public void launchNewVideoTakeActivity(boolean autoStart, boolean checkSo, int entranceType, String extra);
public void setPlayVideoBtnDisplay(boolean display);
public void showStartDownload();
public void showDownloadCompleted(boolean success);
public void storyPreLoadCompleted(String category, String uin);
public void LoadMoreCompleted(boolean repositoryUpdated, boolean isEnd);
public void showEmptyView(boolean display);
public void requestDataCompleted();
public void openMyStoryListView(boolean open);
}Activity Implementing the View
public class QQStoryMainAcitivty extends QQStoryBaseActivity implements IMyStoryListView {
protected StoryHomePushYellowBarHandler mStoryHomePushYellowBarHandler = new StoryHomePushYellowBarHandler();
protected MystoryListView mainListView;
protected IMyStroyPresenter myStoryListPresenter;
@Override
protected boolean doOnCreate(Bundle savedInstanceState) {
super.doOnCreate(savedInstanceState);
mainListView = (MystoryListView) super.findViewById(R.id.qqstory_story_main_listview);
// Presenter
myStoryListPresenter = new StoryListPresenter(this);
myStoryListPresenter.setIView(this);
return true;
}
@Override
public void onStartAutoRequestFromNet() {
startTitleProgress();
mainListView.pullToRefresh();
mStoryHomePushYellowBarHandler.clearYellowBar();
myStoryListPresenter.requestAllDataFromNet();
}
private void startTitleProgress() {
// do more
}
}The user pulls to refresh, triggering onStartAutoRequestFromNet in the Activity; the Presenter’s requestAllDataFromNet handles the business logic.
Presenter Implementation
public class StoryListPresnter implements IMyStroyPresenter {
protected IMyStoryListView mIView;
protected FeedItem mFeedItem;
protected ParallelStepExecutor mRequestNetDataExecutor;
@Override
public void onCreate(boolean needUpdateFromNet) {
// Lifecycle handling
mFeedItem = new FeedItem();
}
@Override
public void setIView(IMyStoryListView IView) {
// Set the View interface (Activity or Fragment)
mIView = IView;
}
public boolean requestAllDataFromNet() {
mRequestNetDataExecutor.addStep(new GetUserSelfInfoStep(null))
.addStep(new ReportWatchVideoListStep(StoryListPresenter.this))
.addStep(new GetUserGuideInfoStep(StoryListPresenter.this))
.onCompleted(new SimpleStepExector.CompletedHandler() {
@Override
public void done(FeedItem item) {
// Process Model layer
mFeedItem = item;
mIView.openMyStoryListView(mFeedItem); // Update View via interface
}
}).run();
return true;
}
}Pros and Cons of MVP
Advantages
Strong decoupling.
Clear module responsibilities and hierarchy.
Presenter reuse across multiple tabs.
Facilitates unit testing.
Prevents Activity memory leaks.
Disadvantages
Heavy; each View requires a Presenter, leading to many methods.
Presenter can become bulky for complex business logic.
Increased code complexity and learning curve.
Method count can explode in large projects like QQ.
Lego Page Structuring
Beyond MVP, the article proposes a Lego‑style page structuring approach, which treats each page region as an independent module with its own layout, data source, event bindings, and lifecycle, rather than a simple reusable component.
Key differences between componentization and Lego page structuring:
Components are generic and lack business logic; Lego modules embed business logic.
Lego aims at maintainability and project management; component reuse is optional.
Components and Lego can coexist: component + data + logic = Lego.
Analyzing Lego Characteristics
Each Lego can have its own data source, but it may also receive data from other Legos, and Legos form a parent‑child hierarchy managed by a top‑level Lego.
public FeedCommentLikeLego(Context context, Activity activity, ViewGroup parentView, HomeFeedItem feedItem, int feedType) {
super(context, parentView);
mHomeFeedItem = feedItem;
mFeedItem = feedItem.mFeedBasicItem;
mActivity = activity;
mFeedType = feedType;
mLikeManager = (LikeManager) SuperManager.getAppManager(SuperManager.LIKE_MANAGER);
mParentView = LayoutInflater.from(context).inflate(R.layout.qqstory_feed_commentlike_view, parentView, true);
// Page structure
FeedCommentLego commentLego = new FeedCommentLego(mContext, mParentView, mFeedItem, mFeedType);
FeedLikeLego likeLego = FeedLikeLego.createIndexFeedLikeLego(mContext, activity, mParentView, mFeedItem, mFeedType);
addLego(LEGO_KEY_COMMENT, commentLego);
addLego(LEGO_KEY_LIKE, likeLego);
commentLego.feed(mHomeFeedItem.getCommentList());
likeLego.feed(mHomeFeedItem.getLikeEntryList());
boot();
}The constructor shows that the parent Lego manages two child Legos (comment and like), supplies them with data, and controls their lifecycle.
In list pages, data is often merged into a single network response, feeding multiple Legos without each Lego initiating its own request. In detail pages, a Lego may fetch its own data via a dedicated LegoDataProvider:
@Override
public LegoDataProvider getDataProvider() {
return new FeedLikeDataProvider(this, mIsDetailPage);
}Overall, a Lego module encapsulates network requests, data processing, event binding, reporting, and error handling for a specific page block, providing a clear, maintainable functional unit.
Conclusion
Lego page structuring emphasizes modular decomposition of a page, achieving decoupling, high readability, and unified optimization. While still experimental, it offers lighter code and clearer logic compared to traditional MVP, though top‑level Lego complexity and interface constraints remain challenges.
Tencent TDS Service
TDS Service offers client and web front‑end developers and operators an intelligent low‑code platform, cross‑platform development framework, universal release platform, runtime container engine, monitoring and analysis platform, and a security‑privacy compliance suite.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
