Android MVP模式基类结构

来源:互联网 发布:mysql的insert into 编辑:程序博客网 时间:2024/05/18 22:53

相信MVP模式在Android程序中已经使用的非常广泛了,下面我来介绍一种MVP模式的基类结构。




整个结构以Fragment为核心,首先定义了BaseFragment继承于Fragment,主要是实现了把要加载的Fragment作为参数的launch方法,并在launch方法中实际加载绑定了目标Fragment的BaseActivity。除此之外,BaseFragment中还实例化并保存了一系列helper,比如viewHelper,dialoagHelper,broadCastHelper等等,从而可以在子类中方便的处理相关任务。

    public void launch(Class<? extends Fragment> fragment,                       Bundle args4fragment, int reqCode) {        launch(BaseActivity.class, fragment, args4fragment, reqCode);    }    public void launch(Class<? extends BaseActivity> activity,                       Class<? extends Fragment> fragment, Bundle args4fragment, int reqCode) {        if (getActivity() == null || isDetached()) {            return;        }        Intent in = BaseActivityHelper.builder(this, activity).setFragment(fragment, args4fragment).build();        if (reqCode != 0) {            getHostFragment().startActivityForResult(in, reqCode);        } else {            getHostFragment().startActivity(in);        }    }


随后的子类BaseLinearFragment,则是在BaseFragment的基础上加载了一个包含两个ViewStub的layout,并依照head和body的区分又定义了一些方法。

<?xml version="1.0" encoding="utf-8"?><LinearLayout    android:id="@+id/content"    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <ViewStub        android:id="@+id/head"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout="@layout/navbar"/>    <ViewStub        android:id="@+id/body"        android:layout_width="match_parent"        android:layout_height="match_parent"/></LinearLayout>

    @Override    protected final void initInflateViewStub(View parent) {        super.initInflateViewStub(parent);        int headLayoutId = getHeadLayoutId();        if (headLayoutId != EmptyConst.EMPTY_ID) {            setupHead(viewHelper.inflateViewStub(R.id.head, headLayoutId));        }        setupBody(viewHelper.inflateViewStub(R.id.body, getBodyLayoutId()));    }    @LayoutRes    protected int getHeadLayoutId() {        return R.layout.navbar;    }


到了BaseRequestFragment这,就开始处理网络请求相关的任务了。它实现了IRequestView接口,可以依照 成功获取数据/成功但数据为空/请求失败 三种情况来处理网络请求的结果。


public interface IRequestView {    void showLoading();    void showContent();    void showEmpty();    @DrawableRes    int getEmptyImageResId();    String getEmptyText();    void showError();}

同时相应的BaseRequestPresenter实现了IPresenter接口,可以对IRequestView进行绑定,并持有IRequestView。

public interface IPresenter<V extends IRequestView> {    void attachView(V view);    void detachView(V view);}

SingleRequestFragment则在BaseRequestFragment的基础上终于建立起MVP模式,通过SingleRequestContract来和SingleRequestPresenter相互持有,用来处理加载Fragment时要发Api来获取一个数据结构进行渲染的情形。

public interface SingleRequestContract {    interface View<T> extends IRequestView {        Context getContext();        void render(@NonNull T data);    }    interface Presenter<T> extends IPresenter<View<T>> {        void onSaveInstanceState(Bundle outState);        void restoreSavedInstance(Bundle savedInstanceState);                void load(@Nullable RequestCallback<T> callback);    }}


ListRequestFragment同样是继承于BaseRequestFragment,但却比SingleRequestFragment复杂的多。它是用来处理要发Api来获取一个列表,并以listView为主体的Fragment。为此,ListRequestFragment持有一个listView,实现了与此listView相关的下拉刷新、加载更多、列表为空、列表加载错误等诸多方法。

public interface RequestListContract {    interface View<ListItem> extends IRequestView {        void renderDataList(List<ListItem> dataList, boolean canLoadMore, boolean refresh);        void toastNetworkError(NetApiException error);        void showNetworkError(boolean refresh);        boolean showListLoading();        void dismissListLoading();    }    interface Presenter<ListItem> extends IPresenter<View<ListItem>> {        void load();        void refresh(boolean showListLoading);        void loadMore();    }}

而相应的SingleRequestPresenter和ListRequestPresenter除了实现Contract中的方法之外,主要是实现了一个默认回调DefaultCallback,在其中对返回的结果进行了处理。如果请求成功,则进行数据解析,并把解析后的结构传给Fragment进行渲染。



综上所述,使用这套MVP基类结构,并把它与网络请求库(Volley、Retrofit)、数据解析库(gson)搭配使用后,开发者可以专注于UI绘制、请求发送,对于请求的结果处理几乎不用再花费什么工作量。特别是对于以列表为主体的界面而言,由于存在多种刷新机制,同时也存在多种出错机制,如果从头写非常麻烦。而如果在此结构上开发,感觉就会像由地狱来到了天堂...

原创粉丝点击