關于Android MVP模式的思考

NewAE77 7年前發布 | 5K 次閱讀 安卓開發 Android開發 移動開發

這一周對現有的Android項目進行了框架重構,使用MVP模式來重新構建整個項目和包結構。今天就來總結一下我在這個過程中理解和實踐吧。

MVP概述

MVP是指Model,View和Presenter的縮寫,是MVC模式的一種改進版。MVP是一種非常適合Android應用的開發模式,它 將把邏輯相關代碼從presentation Layer中分離出去 ,所以,所有界面應該顯示什么和界面如何顯示這些是相互分離的, 在理想狀態下,MVP模式可以隨意切換視圖顯示的形式。

但是,需要首先聲明的是,MVP并不是 一個框架模式 ,它只負責presentation Layer。在Android項目中,還可能存在Domain Layer和Data Layer,它們分別負責業務邏輯和數據存儲。

The presenter

The presenter充當的是view和model模塊中間人的角色。它從model模塊獲得數據并發送給view模塊。 但是不同于MVC,presenter模塊也決定用戶和界面交互時界面如何響應 。

The View

View模塊,一般由Activity或者Fragment實現,每個View實例一般都包含一個presenter實例的引用,并負責實例化presenter。理想情況下,你可以使用dagger來實現依賴注入。view的任務就是當用戶操作界面時,調用presenter實例的功能來進行響應。

The Model

在設計良好的分層架構中,model應該只是domain layer和業務邏輯的入口,比如說, clear architecture 。但是你也可以把所有界面顯示無關的邏輯都作為model。

MVP示例

關于MVP架構的實例有很多,比如 google官方架構 。這里我就給出一下我重構項目一個模塊的類圖,然后大致說一下實現。

首先定義了 BaseView 和 BasePresenter 兩個接口,實現了 BaseActivity 和 BaseFragment 兩個基礎類。需要注意的是,因為每個View都需要持有一個特定類型的presenter對象,所以,在 BaseView 定義時,使用了范型。除此之外,你可以在 initPresenter 函數中構造出所需要的presenter對象。 showLoading 和 stopLoading 函數是所有視圖進行網絡數據加載時所需要的方法,其具體使用場景后邊可以看到,這里這兩個接口是在 BaseActivity 中實現的。

public interface BaseView<T> {
    void showLoading();
    void stopLoading();
    void initPresnter();
    T getPresenter();
}

public interface BasePresenter {

}

public class BaseActivity extends Activity{
    public void showLoading() {
    }

    public void stopLoading() {
    }
}

public class BaseFragment extends Fragment {
    public void showLoading() {

    }

    public void stopLoading() {

    }
}

然后是data模塊中的相關類和接口的定義。我們在 DataContract 接口中定義所有相關的view和data。

public interface DataContract {
    interface DataView extends BaseView<DataPresenter> {
        void showFragment(BaseFragment fragment);
    }
    interface DataPresenter extends BasePresenter {
        void switchToDataList();
        void switchToDataTree();
    }
    interface DataListView extends BaseView<DataListPresenter> {
        void showDataList(List<String> data);
    }
    interface DataListPresenter extends BasePresenter {
        void loadDataList();
    }
    interface DataTreeView extends BaseView<DataTreePresenter> {}
    interface DataTreePresenter extends BasePresenter {}
}

在 DataContract 接口中,我們可以清晰的看到這個模塊中所有的view和presenter類型和他們的接口。這樣無疑可以幫助其他程序員快速了解本模塊的業務邏輯。下面,我們來看一下 DataListFragmnet 和 DataListPresenter 的實現。

public class DataListFragment extends BaseFragment implements DataContract.DataListView {
    private DataContract.DataListPresenter mPresenter;
    @Override
    public void initPresnter() {
        mPresenter = new DataListPresenter(this);
    }
    @Override
    public DataContract.DataListPresenter getPresenter() {
        return mPresenter;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initPresnter();
        //需要加載數據或者接收到界面點擊事件時,調用presenter接口進行初始化或者響應。
        mPresenter.loadDataList();
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_data_list, container, false);
    }
    @Override
    public void showDataList(List<String> data) {
        //將數據傳給adapter等數據展示的視圖
    }
}

public class DataListPresenter implements DataContract.DataListPresenter {
    private DataContract.DataListView mView;
    public DataListPresenter(DataContract.DataListView view) {
        super();
        this.mView = view;
    }

    @Override
    public void loadDataList() {
        //調用baseview的接口,這些接口實現在baseFragment或者BaseActivity中
        mView.showLoading();
        //getdata from network
        mView.stopLoading();
        mView.showDataList(Arrays.asList("a","b","c"));
    }
}

上述代碼中有很多可以好好思考的地方。首先是 showLoading 和 stopLoading 這兩個函數。這兩個函數接口定義在 BaseView ,實現在 BaseFragment ,所以當 DataListFragment 繼承了 BaseFragment 并且實現了 BaseView 時,它并不需要再次定義上述兩個接口,畢竟在一個app中,網絡加載時的laoding動畫一般都是一致的。然后是view和presenter之間函數調用的問題。首先,view在需要初始化或者需要處理點擊事件時,需要調用presenter的函數,而不是自己來進行處理。而且二者之間的數據傳遞必須是presenter調用view的接口傳遞給view數據,而不是view調用presenter接口獲得數據然后自己展示。

 

來自:http://remcarpediem.com/2017/03/12/關于Android-MVP模式的思考/

 

 本文由用戶 NewAE77 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!