android mvp模式

Android Mvp 如今被普遍的應用在Android開發項目中,如今個人項目也使用了這種開發設計模式。java

當咱們的項目越龐大,複雜,參與的人員愈來愈多的時候,mcp的優勢就展示出來了。設計模式

Mvc與Mvp的區別:服務器

Mvc模式:網絡

Activity應該是屬於View這一層。而實質上,它既承擔了View,同時也包含一些Controller的東西在裏面。這對於開發與維護來講不太友好,耦合度大高了。架構

MVC模式的結構分爲三部分,實體層的Model,視圖層的View,以及控制層的Controller。mvc

  • 其中View層其實就是程序的UI界面,用於向用戶展現數據以及接收用戶的輸入異步

  • 而Model層就是JavaBean實體類,用於保存實例數據ide

  • Controller控制器用於更新UI界面和數據實例佈局

Mvp模式:單元測試

把Activity的View和Controller抽離出來就變成了View和Presenter,這就是MVP模式。mvp屬於mvc的一個增強版設計模式。

在Android開發中Activity和fragment都屬於view層,負責展示給用戶的UI控件,以及接收用戶的輸入,此外還要負責展示的生命週期的工做。若是在它們代碼層在加上業務邏輯判斷,就會使的代碼看起來臃腫,不利於維護。並且多人進行開發同一個項目時,對於同一界面的增改增多,就會出現衝突,不利於多人開發。因此咱們採用mvp模式代替mvc,mvp中view展示層,只負責交互,展示,不負責邏輯判斷。Presenter負責全部的邏輯實現,Model負責獲取數據用的。

MVP的好處:

1.分離了視圖邏輯和業務邏輯,下降耦合度。

2.Activity只負責生命週期和與用戶交互的工做,代碼比較簡潔。

3.視圖邏輯和業務邏輯分別抽象到View和Presenter的接口中去,提升代碼的可閱讀性。

4.Presenter抽象成接口,能夠實現多個實現類,很方便的進行單元測試。

 其中最重要的有三點:

Activity 代碼變得更加簡潔

相信不少人閱讀代碼的時候,都是從Activity開始的,對着一個1000+行代碼的Activity,看了都以爲難受。

使用MVP以後,Activity就能瘦身許多了,基本上只有FindView、SetListener以及Init的代碼。其餘的就是對Presenter的調用,還有對View接口的實現。這種情形下閱讀代碼就容易多了,並且你只要看Presenter的接口,就能明白這個模塊都有哪些業務,很快就能定位到具體代碼。Activity變得容易看懂,容易維護,之後要調整業務、刪減功能也就變得簡單許多。

方便進行單元測試

通常單元測試都是用來測試某些新加的業務邏輯有沒有問題,若是採用傳統的代碼風格(習慣性上叫作MV模式,少了P),咱們可能要先在Activity裏寫一段測試代碼,測試完了再把測試代碼刪掉換成正式代碼,這時若是發現業務有問題又得換回測試代碼,咦,測試代碼已經刪掉了!好吧從新寫吧……

MVP中,因爲業務邏輯都在Presenter裏,咱們徹底能夠寫一個PresenterTest的實現類繼承Presenter的接口,如今只要在Activity裏把Presenter的建立換成PresenterTest,就能進行單元測試了,測試完再換回來便可。萬一發現還得進行測試,那就再換成PresenterTest吧。

避免 Activity 的內存泄露

Android APP 發生OOM的最大緣由就是出現內存泄露形成APP的內存不夠用,而形成內存泄露的兩大緣由之一就是Activity泄露(Activity Leak)(另外一個緣由是Bitmap泄露(Bitmap Leak))。

Java一個強大的功能就是其虛擬機的內存回收機制,這個功能使得Java用戶在設計代碼的時候,不用像C++用戶那樣考慮對象的回收問題。然而,Java用戶老是喜歡隨便寫一大堆對象,而後幻想着虛擬機能幫他們處理好內存的回收工做。但是虛擬機在回收內存的時候,只會回收那些沒有被引用的對象,被引用着的對象由於還可能會被調用,因此不能回收。

Activity是有生命週期的,用戶隨時可能切換Activity,當APP的內存不夠用的時候,系統會回收處於後臺的Activity的資源以免OOM。

採用傳統的MV模式,一大堆異步任務和對UI的操做都放在Activity裏面,好比你可能從網絡下載一張圖片,在下載成功的回調裏把圖片加載到 Activity 的 ImageView 裏面,因此異步任務保留着對Activity的引用。這樣一來,即便Activity已經被切換到後臺(onDestroy已經執行),這些異步任務仍然保留着對Activity實例的引用,因此係統就沒法回收這個Activity實例了,結果就是Activity Leak。Android的組件中,Activity對象每每是在堆(Java Heap)裏佔最多內存的,因此係統會優先回收Activity對象,若是有Activity Leak,APP很容易由於內存不夠而OOM。

採用MVP模式,只要在當前的Activity的onDestroy裏,分離異步任務對Activity的引用,就能避免 Activity Leak。

說了這麼多,沒看懂?好吧,我本身都沒看懂本身寫的,咱們仍是直接看代碼吧。

上面一張簡單的MVP模式的UML圖,從圖中能夠看出,使用MVP,至少須要經歷如下步驟:

  1. 建立IPresenter接口,把全部業務邏輯的接口都放在這裏,並建立它的實現PresenterCompl(在這裏能夠方便地查看業務功能,因爲接口能夠有多種實現因此也方便寫單元測試)

  2. 建立IView接口,把全部視圖邏輯的接口都放在這裏,其實現類是當前的Activity/Fragment

  3. 由UML圖能夠看出,Activity裏包含了一個IPresenter,而PresenterCompl裏又包含了一個IView而且依賴了Model。Activity裏只保留對IPresenter的調用,其它工做所有留到PresenterCompl中實現

  4. Model並非必須有的,可是必定會有View和Presenter

經過上面的介紹,MVP的主要特色就是把Activity裏的許多邏輯都抽離到View和Presenter接口中去,並由具體的實現類來完成。這種寫法多了許多IView和IPresenter的接口,在某種程度上加大了開發的工做量,剛開始使用MVP的小夥伴可能會以爲這種寫法比較彆扭,並且難以記住。其實一開始想太多也沒有什麼卵用,只要在具體項目中多寫幾回,就能熟悉MVP模式的寫法,理解TA的意圖,以及享♂受其帶來的好處。

    Talk is cheap, let me show you the code!

1.咱們初始化初始化接口BaseView,方法爲向activity顯示的回調方法。

2.初始化接口Presenter類,用戶處理業務邏輯的抽象類。

3.初始化接口Contract類,用來鏈接接口View和接口Presenter的鏈接類

4.Presenter處理業務邏輯的類的具體實現

/**
 * 做爲view與Model交互的中間紐帶,處理與用戶交互負責的邏輯
 */

public class RecommendPresenter implements RecommendContract.Presenter{

    private RecommendModel mModel;// 訪問網絡的Model

    private RecommendContract.View mView;// 負責activity的回調。

    public RecommendPresenter(RecommendContract.View view) {
        this.mView = view;
        this.mModel = new RecommendModel();
    }

    @Override
    public void requestDatas() {
        mView.showLodading();// 通知彈出加載對話框回調
        // 訪問網絡獲取 推送  數據的接口。
        mModel.getApps(new Callback<PageBean<AppInfo>>() {
            @Override
            public void onResponse(Call<PageBean<AppInfo>> call, Response<PageBean<AppInfo>> response) {

                if(response !=null){
                    // 返回數據回調
                    mView.showResult(response.body().getDatas());
                }
                else{
                    // 訪問數據爲空的回調
                    mView.showNodata();
                }
                    // 關閉彈出的加載的對話框
                mView.dimissLoading();

            }

            @Override
            public void onFailure(Call<PageBean<AppInfo>> call, Throwable t) {
                // 關閉加載對話框回調
                mView.dimissLoading();
                // 彈出錯誤選擇框
                mView.showError(t.getMessage());

            }
        });


    }
}

5.Activity的具體實現

/**
* 與用戶展現的activity或fragment的實現。
*/
public class RecommendFragment extends Fragment implements RecommendContract.View {

    @BindView(R.id.recycle_view)
    RecyclerView mRecyclerView;


    private ProgressDialog mMProgressDialog;
    private RecommendPresenter mMPredenter;
    private RecomendAppAdatper mAdatper;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View mView = inflater.inflate(R.layout.fragment_recomend, container, false);
        ButterKnife.bind(this, mView);
        mMProgressDialog = new ProgressDialog(getActivity());// 加載框 初始化
        mMPredenter = new RecommendPresenter(this);
        isCreateView = true;
        return mView;
    }

   

    private void initRecycleView(List<AppInfo> datas) {
        //爲RecyclerView設置佈局管理器
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        //爲RecyclerView設置分割線(這個能夠對DividerItemDecoration進行修改,自定義)
        mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
        //動畫
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdatper = new RecomendAppAdatper(getActivity(), datas);
        mRecyclerView.setAdapter(mAdatper);
    }


    @Override
    public void showResult(List<AppInfo> datas) {
        initRecycleView(datas);
    }

    @Override
    public void showNodata() {
        Toast.makeText(getActivity(), "暫時無數據,請吃完飯再來", Toast.LENGTH_LONG).show();
    }

    @Override
    public void showError(String msg) {
        Toast.makeText(getActivity(), "服務器開小差了:" + msg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void showLodading() {
        mMProgressDialog.show();
    }

    @Override
    public void dimissLoading() {
        if (mMProgressDialog.isShowing()) {
            mMProgressDialog.dismiss();
        }
    }

}

  這樣就架構出來了MVP模式代碼。

相關文章
相關標籤/搜索