应用MVP模式写出可维护的优美Android应用
在Android開發(fā)中,我們常常會動輒寫出數(shù)千行的Java類,而當(dāng)一個Activity有4、5千行的時候,想找一個邏輯在哪兒就會顯得異常痛苦了。比如想在數(shù)據(jù)加載錯誤的時候,顯示一個提示信息,上上下下得找很久。
最近用了MVP模式后,我覺得找到了一個不錯的框架級解決方法。
首先看看
MVP是什么
MVP是MVC模式的一個衍生物,可以簡單看下圖。在MVP模式中,V層完全和M層(在Android中可能是Model、DAO、或者通用的business logic)分開。在中間用P層分隔,從而把數(shù)據(jù)有關(guān)和UI有關(guān)完全分離開。
主流的MVP又有兩種實現(xiàn)方式
1)Activity、Fragment、View直接作為V層。Presenter通過繼承被視圖層實例化或者通過注入得到。這樣Presenter在理想狀態(tài)下可以完全和Android分離,也剝離了activity的那些生命周期。
2)Activity和Fragment作為P層,另外單獨創(chuàng)建一個V層類,持有Activity里面的各種view,并提供接口讓Activity調(diào)用來更新界面。
為了讓V層和P層解耦,通常P層對V層的持有是通過interface的。
一個完整的mvp事件流可以是
sample
這里用第一種實現(xiàn)方式來做個例子。
每個Activity繼承的基類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /** * A {@link BaseActivity} that uses an {@link MvpPresenter} to implement a MVP Architecture. */ public abstract class MvpActivity<P extends MvpPresenter> extends BaseActivity implements MvpView { protected P presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = createPresenter(); if (presenter == null) { throw new NullPointerException("Presenter is null"); } presenter.attachView(this); } @Override protected void onDestroy() { super.onDestroy(); presenter.detachView(false); } /** * Instantiate a presenter instance * * @return The {@link MvpPresenter} for this view */ protected abstract P createPresenter(); } |
暴露給Presenter的View層接口:
| 1 2 3 4 5 | /** * The root view interface for every mvp view */ public interface MvpView { } |
Presenter層,告別了繁瑣的activity周期,只有創(chuàng)建和銷毀兩個狀態(tài)接口。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * The base interface for each mvp presenter */ public interface MvpPresenter<V extends MvpView> { /** * Set or attach the view to this presenter */ void attachView(V view); /** * Will be called if the view has been destroyed. Typically this method will be invoked from * <code>Activity.detachView()</code> or <code>Fragment.onDestroyView()</code> */ void detachView(boolean retainInstance); } |
比如這次做新的留言板需求,我就寫了
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class QZoneLeaveMessageActivity extends MvpActivity<LeaveMessagePresenter> implements LeaveMessageView, OnClickListener { } // Lce就是Load Content Error,通用的load數(shù)據(jù)View接口 public interface MvpLceView<M> extends MvpView { void showLoading(boolean pullToRefresh); void showContent(); void showError(Throwable e, boolean pullToRefresh); void setData(M data); void loadData(boolean pullToRefresh); } public interface LeaveMessageView extends MvpLceView<List<TemplateData>> { ... } public class LeaveMessagePresenter extends MvpBasePresenter<LeaveMessageView> implements QZoneServiceCallback { } |
這么些類來應(yīng)用了MVP模式,個人覺得是比以前清晰了不少。
個人心得
- 不要把presenter當(dāng)做OnClickListener,View才是來處理用戶輸入和給予反饋的,presenter不應(yīng)該知道view內(nèi)部的邏輯來判斷點擊某個按鈕后做出什么相應(yīng)。一個簡單的判斷某個邏輯是否屬于presenter的方法是,如果view層不是android,而是java桌面應(yīng)用,那你的presenter層是不是還能不做更改地work。
- view層只做presenter層讓你做的,比如上圖view層用戶點了一個按鈕,View調(diào)用了presenter.loadUsers,presenter一邊在background thread去getUsers,一邊調(diào)用了view.showLoading(),view層不該自說自話地showLoading。不過如何showLoading,比如展示怎么樣的動畫,那就是view層的內(nèi)部矛盾了。
- 一個很大的好處,就是通過MVP,異步變得很清晰,view層的東西完全是主線程的,只需要等著presenter調(diào)就行了。
總結(jié)
以上是生活随笔為你收集整理的应用MVP模式写出可维护的优美Android应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webform 转 MVC 飞一般的感觉
- 下一篇: 聊聊asp.net中Web Api的使用