
本文的合集已經(jīng)編著成書,高級(jí)Android開發(fā)強(qiáng)化實(shí)戰(zhàn),歡迎各位讀友的建議和指導(dǎo)。在京東即可購(gòu)買:https://item.jd.com/12385680.html

在Android中使用MVC架構(gòu), 無(wú)法完全分離View層與Model層中的UI邏輯與業(yè)務(wù)邏輯, 導(dǎo)致模塊耦合, 無(wú)法全部覆蓋測(cè)試. 因而引入進(jìn)化版MVP(Model-View-Presenter)架構(gòu), 在Model層傳輸數(shù)據(jù)至View層時(shí), 使用Presenter層封裝邏輯. Google在Android框架指引中, 也采用MVP架構(gòu), 還添加若干細(xì)節(jié), 源碼參考Android架構(gòu)的RxJava版本.
三個(gè)架構(gòu)的分析均已完成, 參考MVC, MVP, MVVM.
MVP架構(gòu)
MVP架構(gòu)包含三大模塊, 即Model, View, Presenter.
- Model: 即數(shù)據(jù)層, 負(fù)責(zé)處理業(yè)務(wù)邏輯, 監(jiān)聽(tīng)網(wǎng)絡(luò)與數(shù)據(jù)庫(kù)接口.
- View: 即界面(UI)層, 展示數(shù)據(jù), 響應(yīng)用戶事件并通知Presenter.
- Presenter: 即展示層, 接收Model的數(shù)據(jù), 處理UI邏輯, 并管理View的狀態(tài), 根據(jù)View層事件提供展示數(shù)據(jù).

View層與Presenter層關(guān)系非常緊密, 相互引用, 并且一一對(duì)應(yīng). Presenter支持單元測(cè)試, View被抽象成若干顯示接口, 供Presenter調(diào)用, View處理Android邏輯, Presenter處理UI邏輯. View和Presenter的接口信息, 放置在一個(gè)邏輯清晰的接口類(合同)中.
Model層
Model負(fù)責(zé)獲取或存儲(chǔ)在遠(yuǎn)程或本地的數(shù)據(jù). 例如, 在處理數(shù)據(jù)時(shí), Model先檢索本地?cái)?shù)據(jù), 為空則請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù), 并同步本地, 再顯示.
在構(gòu)造器中, 添加本地與遠(yuǎn)程數(shù)據(jù)源的接口類, 數(shù)據(jù)源內(nèi)分離邏輯與實(shí)現(xiàn).
public static TasksRepository getInstance(TasksDataSource tasksRemoteDataSource,
TasksDataSource tasksLocalDataSource) {
if (INSTANCE == null) {
INSTANCE = new TasksRepository(tasksRemoteDataSource, tasksLocalDataSource);
}
return INSTANCE;
}
View層
View與Presenter配合使用, 負(fù)責(zé)展示數(shù)據(jù), 通知Presenter響應(yīng)用戶事件. Activity(或Fragment)是View層. View與Presenter相互對(duì)應(yīng). View繼承自含有設(shè)置Presenter的接口.
public interface BaseView<T> {
void setPresenter(T presenter);
}
public interface TasksContract {
interface View extends BaseView<Presenter> {
// ...
}
// ...
}
View在onResume中注冊(cè)Presenter, 在onPause中釋放Presenter.
@Override
public void onResume() {
super.onResume();
mPresenter.subscribe();
}
@Override
public void onPause() {
super.onPause();
mPresenter.unsubscribe();
}
當(dāng)用戶執(zhí)行動(dòng)作時(shí), View截獲事件, 通過(guò)Presenter接口傳遞事件給Presenter處理. 完成后, Presenter通過(guò)View接口傳遞數(shù)據(jù)給View顯示或反饋. 因此, View與Presenter緊密關(guān)聯(lián), 接口也相互對(duì)應(yīng).
View使用Espresso進(jìn)行UI測(cè)試.
Presenter層
Presenter與View一起創(chuàng)建, 并綁定View與Model的引用. 通過(guò)View接口, 在構(gòu)造器中, 創(chuàng)建View與Presenter的相互引用.
public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {
mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
mTasksView = checkNotNull(tasksView, "tasksView cannot be null!"); // 引用View
mSubscriptions = new CompositeSubscription();
mTasksView.setPresenter(this); // 在View中設(shè)置Presenter的引用
}
Presenter繼承BasePresenter, 提供綁定與釋放的方法. 確保在頁(yè)面關(guān)閉時(shí), 終止線程中的網(wǎng)絡(luò)請(qǐng)求.
public interface BasePresenter {
void subscribe();
void unsubscribe();
}
public interface TasksContract {
interface Presenter extends BasePresenter {
// ...
}
// ...
}
當(dāng)用戶執(zhí)行動(dòng)作時(shí), Presenter請(qǐng)求Model, 獲取數(shù)據(jù), 根據(jù)UI邏輯, 在View中顯示. Presenter方法覆蓋全部事件處理邏輯, 與View事件相互對(duì)應(yīng).
優(yōu)缺點(diǎn)
MVP架構(gòu)更好地分離View與Model之間的職責(zé), 解除UI邏輯之間的耦合.
對(duì)于小型項(xiàng)目而言, 與設(shè)計(jì)模式類似, 會(huì)導(dǎo)致過(guò)度設(shè)計(jì), 增加代碼量. 當(dāng)處理復(fù)雜頁(yè)面時(shí), Presenter層會(huì)包含大量UI邏輯與業(yè)務(wù)邏輯, 非常冗余, 并違反單一職責(zé)原理.
MVP架構(gòu)的核心在于Presenter層. Presenter打破Model與View之間的耦合, 創(chuàng)建展示數(shù)據(jù)的通道, 隔離業(yè)務(wù)邏輯, 支持單元測(cè)試. 還有另一個(gè)架構(gòu), MVP的進(jìn)化版MVVM.
OK, that's all! Enjoy it!