欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android MVP模式基类结构

程序员文章站 2024-03-15 19:24:54
...

相信MVP模式在Android程序中已经使用的非常广泛了,下面我来介绍一种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绘制、请求发送,对于请求的结果处理几乎不用再花费什么工作量。特别是对于以列表为主体的界面而言,由于存在多种刷新机制,同时也存在多种出错机制,如果从头写非常麻烦。而如果在此结构上开发,感觉就会像由地狱来到了天堂...