Android MVP架構的使用

前言

在現實項目中,我們經常會遇到這樣一種情況,就是一個Activity類不僅要處理幾種業務邏輯,同時還要兼顧着數據的請求以及UI的操作,這樣造成的後果就是整個類的代碼會出現上千行,更有勝者是幾千行。顯而易見,這種處理方式是不妥的,不僅違反了面向對象中單一職責原則,而且對於整個項目來說,也不利於項目的擴展和維護。(單一職責原則:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。)那麼,面對這種情況,我們該如何去架構整個項目?由於android項目本身就是MVC架構的體現,Activity充當了Controller,所以我們需要一種新的架構去替代MVC。

MVP初步瞭解

MVP:(Model-View-Presenter)它是從MVC模式演變而來的,它與MVC模式相同的地方是,Controller/Presenter負責邏輯的處理,Model提供數據,View負責展示。作爲一種新的模式,MVP與MVC有着一個重大的區別,在MVP中View並不直接使用Model,它們之間的通信是通過Presenter來進行的,所有的交互都發生在Presenter內部,而在MVC中View會從Model中讀取數據而不是通過Controller。

MVC圖示

MVC

MVP圖示

MVP

使用MVP的優點:

  • 模型與視圖完全分離,我們可以修改視圖而不影響模型
  • 可以更高效的使用模型,因爲所有的交互都發生在一個地方,即Presendter內部
  • 我們可以將一個Presenter用於多個視圖,而不需要改變Presenter的邏輯。這個特性非常有用,因爲視圖的變化總是比模型的變化頻繁。
  • 如果我們把邏輯放在Presenter中,那麼我們就可以脫離用戶來測試這些邏輯(單元測試)

MVP在Android中使用

  • View層負責處理用戶時間和視圖部分的展示,在Android中,它可能是Activity或者Fragment類
  • Model層負責訪問數據。數據可以是遠程Server API,本地數據庫或者Share的Preference等
  • Presenter層是鏈接(或適配)View和Model的橋樑

示例

項目結構
這裏寫圖片描述

定義一接口INewsView,作爲View層和Presenter層關聯的紐帶,View層去實現該接口,而Presenter通過INewsView進行改變Activity的UI,同時Presenter類也和Model層進行關聯操作
INewsView接口

public interface INewsView {
    void initView();//初始化控件

    void startLoad();//開始請求數據

    void loadSuccess(List<NewsBean> newsBeanList);//請求成功,數據不爲空

    void loadFail();//請求失敗

    void loadEmpty();//請求成功,數據爲空

}

Activity類去實現該接口,進行UI邏輯操作

public class MainActivity extends AppCompatActivity implements INewsView{

    private NewsPersenter newsPersenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        newsPersenter = new NewsPersenter(this);
        newsPersenter.requestData();
    }

    @Override
    public void initView() {
        //初始化控件
    }

    @Override
    public void startLoad() {
        //請求數據前UI操作
    }

    @Override
    public void loadSuccess(List<NewsBean> newsBeanList) {
        //請求成功,數據不爲空,UI操作
    }

    @Override
    public void loadFail() {
        //請求失敗,UI操作
    }

    @Override
    public void loadEmpty() {
        //請求成功,數據爲空,UI操作
    }
}

NewsPresenter類

public class NewsPersenter {
    private INewsView iNewsView;

    public NewsPersenter(INewsView iNewsView) {
        this.iNewsView = iNewsView;
        this.iNewsView.initView();
    }

    public void requestData() {
        //請求數據前數據前UI操作
        iNewsView.startLoad();
        //請求數據,異步請求
        NewsHttpRequest.requestNewsList(new Callback<List<NewsBean>>() {
            @Override
            public void onResponse(Response<List<NewsBean>> response) {
                if (response == null || response.body() == null || response.body().isEmpty()) {
                    //請求成功,無數據
                    iNewsView.loadEmpty();
                } else {
                    //請求成功,有數據
                    iNewsView.loadSuccess(response.body());
                }
            }

            @Override
            public void onFailure(Throwable t) {
                //請求失敗
                iNewsView.loadFail();
            }
        });
    }
}

NewsHttpRequest類,進行數據請求,Model層操作

public class NewsHttpRequest {

    public static interface INewsRequest {
        @GET("/NewsService/newsList")
        Call<List<NewsBean>> getNewsBeanList();
    }

    public static void requestNewsList(Callback<List<NewsBean>> callBack) {
        Retrofit retrofit = new Retrofit.Builder().baseUrl("http://localhost:8080")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofit.create(INewsRequest.class).getNewsBeanList().enqueue(callBack);
    }
}

ps:當項目比較小,業務邏輯不多的時候,不建議使用MVP模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章