搭建MVP模板框架

本文將記錄自己項目中用到的MVP框架模板,方便同學參考。對於MVP框架不熟的同學,建議看下這篇文章:選擇恐懼症的福音!教你認清MVC,MVP和MVVM

下面看下我項目中的流程圖:


這樣看可能並不是很清晰,大概思路就是V調用P中的請求,P調用M的請求,M請求成功後回調P,P再回調V,最後獲取數據顯示。


下面教大家一步一步來實現這個模板,先看下模塊UML圖:

咋一看好複雜。可能我UML圖畫的不好的原因吧。

首先定義BaseView接口

public interface BaseView<T> {
    void setData(List<T> datas);
    void hideProgress();
    void showProgress();

    interface StudentListView extends BaseView<Student> {
    }
}

其中StudentListView是業務接口,繼承BaseView接口,Student是業務類,如果要擴展業務接口,可以繼續在這個文件添加。

接着定義BasePresenter接口

public interface BasePresenter {
    interface StudentListPresenter extends BasePresenter {
        void requestNetWork(int id);
    }
}

同樣這裏定義了P層的基本接口和業務接口,可以繼承在這裏擴展。
接着定義BasePresenterImpl抽象類

public abstract class BasePresenterImpl<T> {
    protected Reference<T> mViewRef;

    public void attachView(T view) {
        mViewRef = new WeakReference<T>(view);
    }

    protected T getView() {
        return mViewRef.get();
    }

    public boolean isViewAttached() {
        return mViewRef != null && mViewRef.get() != null;
    }

    public void detachView() {
        if (mViewRef != null) {
            mViewRef.clear();
            mViewRef = null;
        }
    }
}
可以看到該抽象類裏面依賴了一個V,同時將V的初始化和銷燬放在這個基礎類裏面。

接着再定義BaseDataBridge接口

public interface BaseDataBridge<T> {
    void addData(List<T> datas);
    void error();
    interface StudentListData extends BaseDataBridge<Student> {
    }
}

這是什麼鬼?要它有何用啊?看命名就知道它是一個橋接接口,用於P和M之間進行回調。裏面可以擴展不同業務的橋接接口。
下面定義一個業務類P的實現:

public class StudentListPresenterImpl extends BasePresenterImpl<BaseView.StudentListView>
        implements BasePresenter.StudentListPresenter, BaseDataBridge.StudentListData {
    private BaseModel.StudentListModel studentListModel;

    public StudentListPresenterImpl() {
        studentListModel = new StudentListModelImpl();
    }

    @Override
    public void requestNetWork(int id) {
        studentListModel.requestStudentList(id, this);
    }

    @Override
    public void addData(List<Student> datas) {
        getView().setData(datas);
    }

    @Override
    public void error() {

    }
}

可以看到它繼承基礎類,實現業務P接口和業務橋接接口。同樣我們看到了裏面組合了M層的業務對象(BaseModel.StudentListModel)。
這個業務P類是該業務的中心類,它裏面既依賴V,又組合M,又實現業務接口和橋接接口。起到了承上啓下的作用。

下面看下BaseModel接口實現:

public interface BaseModel<T> {
    void netWork(T model);
    interface StudentListModel extends BaseModel<BaseDataBridge.StudentListData> {
        void requestStudentList(int id, BaseDataBridge.StudentListData studentListData);
    }
}

裏面同樣是M層的業務接口。業務接口裏面依賴業務橋接接口,這樣的話,M層取得數據之後,可以通過橋接接口回調到P層。

下面舉例業務M的實現類:

public class StudentListModelImpl implements BaseModel.StudentListModel {
    Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void netWork(final BaseDataBridge.StudentListData model) {

    }

    @Override
    public void requestStudentList(int id, final BaseDataBridge.StudentListData studentListData) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    final List<Student> data = new ArrayList<Student>();
                    data.add(new Student("wuliqing"));
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            studentListData.addData(data);
                        }
                    });

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

該業務實現類裏面只是模擬了加載耗時操作並切換到主線程做數據回調。實際應用當中肯定不能這樣寫,推薦用RXJAVA來實現。

舉個我項目中的實現:

public class ImageListModelImpl implements BaseModel.ImageListModel {

    @Override
    public void netWorkList(int id, final int page, final BaseDataBridge.ImageListData imageListData) {

        NetWorkRequest.imageList(id, page, new MySubscriber<BaseBean.ImageListBean>() {
            @Override
            public void onError(Throwable e) {
                imageListData.error();
            }

            @SuppressWarnings("unchecked")
            @Override
            public void onNext(BaseBean.ImageListBean imageListBean) {
                imageListData.addData(imageListBean.getInfo());
            }
        });
    }

}

可以清晰的看到在onNext中做了數據回調。

最後來封裝下MvpActivity:

public abstract class MvpActivity<V, T extends BasePresenterImpl<V>> extends AppCompatActivity {

    protected T mPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter = createPresenter();
        mPresenter.attachView((V) this);
        setContentView(getLayoutId());
        initData();
    }

    protected void initData() {
    }

    protected abstract T createPresenter();

    protected abstract int getLayoutId();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.detachView();
    }

}
可以看到基本就是採用模版方法模式+泛型來做封裝。
子類只要繼承它,傳遞業務類和實現相關函數即可。
舉例如下:
public class MainActivity extends MvpActivity<BaseView.StudentListView, StudentListPresenterImpl>
        implements BaseView.StudentListView {

    @Override
    protected StudentListPresenterImpl createPresenter() {
        return new StudentListPresenterImpl();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initData() {
        mPresenter.requestNetWork(1);
    }

    @Override
    public void setData(List<Student> datas) {
        Toast.makeText(this, "datas = " + datas.toString(), Toast.LENGTH_SHORT).show();
    }

    @Override
    public void hideProgress() {

    }

    @Override
    public void showProgress() {

    }
}
可以看到我們的Activity很簡單,業務流程都交給了P,P又交給M。實現了V和M之間的完全解耦。
好的模板框架給大家分享,希望能幫到大家。


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