ReadHub源碼閱讀筆記(二)dagger+MVP

先來思考一般的MVP模式,view層(活動和碎片)持有一個presenter並實例化,presenter通過構造器或set方法持有view引用。然後view層調用presenter方法,prensenter獲取數據後調用view方法(界面操作)完成一次完整響應。

引入dagger後view層不再需要手動實例化presenter,由框架注入即可,這就是區別。

1.首先定義view和presenter的抽象BaseContract:

public interface BaseContract {

    interface BasePresenter<T extends BaseContract.BaseView> {
        void attachView(T view);

        void detachView();
    }

    interface BaseView {

presenter通過泛型聲明關聯的view類型,所需必要操作有獲取view引用和解綁。view基本操作這裏作者定義了一些網絡錯誤顯示進度條等操作,不是必需。

2.接下來看BaseActivity:(fragment一樣)

public abstract class BaseActivity<T extends BaseContract.BasePresenter> extends RxAppCompatActivity implements BaseContract.BaseView {
    @Nullable
    @Inject
    protected T mPresenter;


持有一個presenter實例,並且聲明需要注入。然後在onCreate中調用presenter的attachView將自身引用交給presenter。

再定義一個BasePresenter類實現BaseContract.BasePresenter:

public class BasePresenter<T extends BaseContract.BaseView> implements BaseContract.BasePresenter<T> {
    protected T mView;

    @Override
    public void attachView(T view) {
        this.mView = view;
    }

    @Override
    public void detachView() {
        if (mView != null) {
            mView = null;
        }
    }
}

這也是方便所有具體presenter不必再實現這兩個方法。


3.開始使用:

Base類已經定義完了,接下來以項目中的一個Fragment爲例,看看怎麼使用。這是一個新聞列表界面,界面向presenter請求顯示列表,presenter獲取網絡數據並調用view的方法更新界面。

首先定義抽象層:

public interface TopicContract {
    interface View extends BaseContract.BaseView {
        void updateTopicData(String order, ArrayList<TopicMo> topicMos);
    }

    interface Presenter extends BaseContract.BasePresenter<View> {
        void getTopicNews(String order);
    }
}

在原有接口上的擴展。

真正的presenter,註釋構造器提供注入。由於繼承了BasePresenter所以不必實現綁定和解綁方法,view層繼承BaseAty和BaseFra不必再實現BaseView的方法也是同理:

public class TopicPresenter extends BasePresenter<TopicContract.View> implements TopicContract.Presenter {
    @Inject
    public TopicPresenter() {
    }

    @Override
    public void getTopicNews(final String order) {
        App.apiService(ReadhubApiService.class)
                .apiTopic(order, Constant.TOPIC_PAGE_SIZE)
                .compose(RxSchedulers.<TopicResp>io_main())
                .compose(mView.<TopicResp>bindToLife())
                .subscribe(new Consumer<TopicResp>() {
                    @Override
                    public void accept(TopicResp topicResp) throws Exception {
                        if (topicResp != null && topicResp.data != null) {
                            //通知view更新界面
                            mView.updateTopicData(order, topicResp.data);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        mView.showFailed();
                    }
                });
    }
}

然後fragment實現view接口(注意聲明presenter類型):

public class TopicFragment extends BaseFragment<TopicPresenter> implements TopicContract.View {

依賴注入:

AndroidSupportInjection.inject(this);

fragment在合適時機調用presenter的getTopicNews方法即可。




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