Android MVP模式基类结构
程序员文章站
2024-03-15 19:24:54
...
相信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);
}
}
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绘制、请求发送,对于请求的结果处理几乎不用再花费什么工作量。特别是对于以列表为主体的界面而言,由于存在多种刷新机制,同时也存在多种出错机制,如果从头写非常麻烦。而如果在此结构上开发,感觉就会像由地狱来到了天堂...
下一篇: A04_开始于一个简单的测试用例