上一篇《Android跟我一起來開發(fā)--微影之開篇》中主要講述了一下寫這些博文的初衷筒扒,以及對項目中數(shù)據(jù)忘苛、架構护奈、框架(依賴)泡嘴、目錄結構作了一些簡單的介紹。接下來本文主要針對MVP架構的個人理解做一個詳細的描述逆济。當然還是站在巨人的肩膀上酌予,我是先通讀了一下各位大神對官方mvp(基礎版)的分析,然后通過實際動手編寫來加深印象幫助自己更好理解奖慌。再次感謝各位大神的無私奉獻(ヽ(≧Д≦)ノ)抛虫。
說到mvp,我們不禁要思考這樣一個人生哲理:我是誰简僧,我來自哪里建椰,我要干什么?讓我們像剝洋蔥一層層剝開你外衣岛马。mvp實際上就是mvc的一個變種棉姐,或者說是進化。在mvc中activity/fragment/view都是屬于view這一層啦逆,負責界面的繪制伞矩、與用戶交互,而實際上它既承擔了View的功能夏志,同時也包含一些Controller的東西乃坤。不僅使代碼看起來臃腫,而且對于開發(fā)與維護來說都不太友好沟蔑。通過把activity/fragment/view中的View和Controller剝離開來形成Presenter湿诊,專職做一些數(shù)據(jù)的處理、邏輯的控制等瘦材。在MVP中厅须,M和V并沒有交集,兩人各自為政食棕,互不干擾朗和,通過P這個老好人作為中間人把三者聯(lián)系起來错沽。通過以下兩張圖可以更清晰的理解mvc和mvp兩者之間的區(qū)別。(圖片來源)
為什么要使用mvp
- 分離了視圖邏輯和業(yè)務邏輯例隆,降低了耦合
- Activity只處理生命周期的任務甥捺,代碼變得更加簡潔
- 視圖邏輯和業(yè)務邏輯分別抽象到了View和Presenter的接口中去,提高代碼的可閱讀性
- Presenter和View被抽象成接口镀层,可以有多種具體的實現(xiàn)镰禾,所以方便進行單元測試
- 把業(yè)務邏輯抽到Presenter中去,避免后臺線程引用著Activity導致Activity的資源無法被系統(tǒng)回收從而引起內存泄露和OOM
具體用法
說到具體的用法就先來po一張目錄結構圖上來唱逢。從結構圖中不難看出吴侦,model中對應mvp的M層,包含本地數(shù)據(jù)和遠程數(shù)據(jù)(Realm數(shù)據(jù)庫和網絡)坞古;
base中主要是基礎類备韧,其中BaseView中最主要的是setPresenter用于view持有presenter的引用。
void setPresenter(T presenter);
presenter包中包含了contract和presenter痪枫。其中contract是一個接口類织堂,主要定義了繼承自baseView和basePresenter的接口,在這里聲明的接口可以一目了然奶陈,通過在V和P中進行實現(xiàn)可以使代碼更清晰簡潔易于管理易阳。
public interface DiscoverContract {
interface View extends BaseView<Presenter> {
boolean isActive();
void showContent(VideoRes videoRes);
void refreshFaild(String msg);
void hidLoading();
}
interface Presenter extends BasePresenter {
void getData();
}
}
下邊是Presenter的實現(xiàn)類,可以看到在presenter的構造方法中持有了對view的引用吃粒,同時調用了view的setPresenter方法綁定了自身使view持有了presenter的引用潦俺,這樣V和P形成了雙向引用的關系。
public class DiscoverPresenter extends RxPresenter implements DiscoverContract.Presenter {
DiscoverContract.View mView;
final String catalogId = "402834815584e463015584e53843000b";
......
public DiscoverPresenter(@NonNull DiscoverContract.View threeView) {
mView = Preconditions.checkNotNull(threeView);
mView.setPresenter(this);
}
@Override
public void getData() {
getNextVideos();
}
......
private void getNextVideos(){......}
}
在官方mvp(基礎版)中是以Fragment作為View的具體載體徐勃,我沒有這么做事示,我是以重寫LinearLayout的自定義view作為具體的view載體。來看一下view的代碼:
public class DiscoverView extends RootView<DiscoverContract.Presenter> implements DiscoverContract.View {
@BindView(R.id.title_name) ColorTextView titleName;
......
public DiscoverView(Context context) { super(context); }
public DiscoverView(Context context, AttributeSet attrs) { super(context, attrs); }
@Override
protected void getLayout() {
inflate(mContext, R.layout.fragment_discover_view, this);
}
@Override
public void setPresenter(DiscoverContract.Presenter presenter) { mPresenter = com.google.common.base.Preconditions.checkNotNull(presenter); }
@Override
public void showError(String msg) {
EventUtil.showToast(mContext, msg);
}
@Override
public void showContent(final VideoRes videoRes) {
......
}
}
下面在來看一下activity頁面僻肖,代碼是不是清爽多了肖爵,View只管view,Presenter只管邏輯檐涝。
public class CollectionActivity extends SwipeBackActivity {
@BindView(R.id.collect_view)
CollectionView collectView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collection);
unbinder = ButterKnife.bind(this);
mPresenter = new CollectionPresenter(collectView, 0);
}
}
至此整個過程就算走完了遏匆。看到這里你可能還是云里霧里谁榜,rootview是什么啊,rxpresenter干嘛的凡纳,各個引用啥時候銷毀啊等等(哇咔咔窃植,憋了這這么久憋出來的把自己都快搞暈了,甩甩臉荐糜,今天就到這了巷怜,下篇再針對以上問題進行補充講解葛超,不對,自我解釋延塑。绣张。。)
qq交流群:138485840
下載地址:微影
源碼地址:Ghost
歡迎大家下載和Star