一直也是用MVP模式,也就结合Rx做网络请求,Rx子线程和UI线程的切换是相当的方便(小白后面准备看下相关的切换的源码)。MVP了,一般有presenter层处理网络请求,以及调用view相关的方法,实现数据和View直接的交互。
从图来看也是View仅仅涉及到Presenter层的交互。当前啦,实际上View里面也有实体类的影子,不过仅仅只是拿实体类进行了界面的相关展示 - 小白使用MVP就是这种情况,比如界面里面会有控件拿实体类进行设置的一些操作:
之前小白有封装过BaseAdapter,那个地方我已经将这个dataModle和控件的绑定放到了一起,如果那种情况下的话,界面里面的东西就更少了。或许还得看你如何做的封装。你不能说就可以完全分离,准确讲应该是减低耦合度! 使结构更加清下,逻辑更加明了。更便于维护和完善。
而MVC耦合度就高了
View涉及到实体类,控制类的相关处理,只能说代码多是一方面,逻辑性也烦,维护起来费劲。以前的东家的工程我现在看起来都有点费劲,该重写了。
关于这个MVVM模式,有童鞋也在用。配合dataBinding据说还可以。很早之前有尝试过案例,小白隐隐感觉貌似还行吧。后面再具体分析看看,借鉴的思路,说不定MVVM更好用妮?
步入正题。。了解了MVP,也尝试使用过的话,如果作为像小白这样的新手,我基本上会写很多presenter,基本就是一个界面一个,而且处理都很类似..加上之前的预处理啥的,基本都是很多相同的处理逻辑和代码。
感觉有点多了,对吧?而且下面还有对应的contract(View和Presenter的纽带)。之前我们也是进行了数据预处理Android-Retrofit2+Rxjava2之网络请求预处理-Func1、Subscriber ,这样的话基本上数据请求都是类似如下的方式(看个分页列表的请求吧):
每个列表页面基本都是这种操作??为何不封装一个请求方法呢? 如果是一个请求方法怎么根据不同的实体类(dataModel)的类型,通过请求的Json进行对应类型的转换呢?
小白起初想法:泛型 之前有接触和实践了泛型,所以小白就想,应该可以试一试.
但问题来了? 像retrifit这种泛型接口定义是不能够被正确执行的(小白本想按照这种思路,最后都写完逻辑了,发现不得行):
以上是不行的,关于这个有网友和我一样,感觉自己像“瓜皮”Retrofit2.0简单封装成统一接口处理网络请求 哈哈...
小白目前是这样的:1. 以String作为data的真实数据类型
2. 然后通过Fastjson将其转换为对应的实体类,然后将其结构返回给请求者的回调(onSuccess方法).
3. 如果你试图将拿到的data直接利用fastjson转换为泛型类型,那样不行的,会报错的(人家本来就需要一个实体类进行转换,你还给一个泛型)
那怎么搞了? 想要封装通用,又不想写太多的请求方法?小白想,可以提供一个接口,有视图界面负责创建和实现转换,并返回泛型类型。
就是这样,可以滴...
而视图里面实现如下:
这样就解决了这个转换实体类的问题。嗯嗯。貌似还可以的样纸。 小白又想,或许可以提供一个string转实体类的管理类,专门定义各种实体类的转换,并返回泛型类型,应该可以这样。后面看看咯...
然后继续回到这个请求接口定义的地方
我把之前需要的参数放到了@Url中进行设置,这样就实现了接口通用。省去了定义多个service的情况。
最后把这个Preseter泛型类型的基础请求服务层搞一下
基本上就有了雏形了。。小白感觉还行,目前还是简化了不少东西。
直接贴上三个相关类:
BaseControlPresenter.java
import com.x.finance.controller.BaseControlContract;
import com.x.finance.net.BaseSubscribers;
import com.x.finance.net.ExceptionHandle;
import com.x.finance.net.ResponseFunc;
import com.x.finance.net.RetrofitManager;
import com.x.finance.net.service.BaseService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/*
*@Description: 请求服务表示层
*@Author: hl
*@Time: 2018/11/21 13:54
*/
public class BaseControlPresenter implements BaseControlContract.Presenter{
private BaseControlContract.View view; ///< 数据【对象】请求
private BaseControlContract.RefreshView refreshView; ///< 数据【对象】列表请求
private BaseService baseService; ///< 请求服务
private List subscriptionList = new ArrayList();
private DataHandler dataHandler;
private DataListHandler dataListHandler;
private BaseControlPresenter(){
this.baseService = RetrofitManager.getInstance()
.getmRetrofit()
.create(BaseService.class);
}
private BaseControlPresenter(BaseControlContract.View _view){
this();
this.view = _view;
}
private BaseControlPresenter(BaseControlContract.RefreshView _refreshView){
this();
this.refreshView = _refreshView;
}
public BaseControlPresenter(BaseControlContract.View _view, DataHandler _dataHandler){
this(_view);
this.dataHandler = _dataHandler;
}
public BaseControlPresenter(BaseControlContract.View _view, DataListHandler _dataListHandler){
this(_view);
this.dataListHandler = _dataListHandler;
}
public BaseControlPresenter(BaseControlContract.RefreshView _refreshView, DataHandler _dataHandler){
this(_refreshView);
this.dataHandler = _dataHandler;
}
public BaseControlPresenter(BaseControlContract.RefreshView _refreshView, DataListHandler _dataListHandler){
this(_refreshView);
this.dataListHandler = _dataListHandler;
}
public BaseControlPresenter(BaseControlContract.View _view, BaseControlContract.RefreshView _refreshView, DataHandler _dataHandler){
this();
this.view = _view;
this.refreshView = _refreshView;
this.dataHandler = _dataHandler;
}
public BaseControlPresenter(BaseControlContract.View _view, BaseControlContract.RefreshView _refreshView, DataHandler _dataHandler, DataListHandler _dataListHandler){
this();
this.view = _view;
this.refreshView = _refreshView;
this.dataHandler = _dataHandler;
this.dataListHandler = _dataListHandler;
}
@Override
public void requestData(final String _funUrl, HashMap _paramList) {
///< 显示进度条
view.showDialog();
///< 加入Token参数
_paramList.put("access_token", UserInfoControlPresenter.getToken());
Subscription subscription = baseService.getData(_funUrl, _paramList)
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<>(new ResponseFunc.CallMe() {
@Override
public D onCall(String data, String requestTime) {
return dataHandler.String2Data(data);
}
}))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseSubscribers(view) {
@Override
public void onCompleted() {
view.disDialog();
}
@Override
public void onErrors(ExceptionHandle.ResponeThrowable responeThrowable) {
///< 接下来就可以根据状态码进行处理...
int statusCode = responeThrowable.code;
switch (statusCode) {
case ExceptionHandle.ERROR.TOKEN:
UserInfoControlPresenter.clearAcount();
view.showToast("你的账号异常,请重新登录,谢谢!");
break;
default:
view.showToast(responeThrowable.message);
break;
}
onCompleted();
}
@Override
public void onNext(D data) {
view.onSucess(data);
}
});
subscriptionList.add(subscription);
}
@Override
public void requestDataList(final String _funUrl, final int _pageNum, final boolean _bIsRefresh) {
///< 不是刷新,则显示进度条加载
if (!_bIsRefresh){
///< 显示进度条 - 首次刷新会显示,其他都是空运行
refreshView.showDialog();
}
Subscription subscription = baseService.getDataList(_funUrl, _pageNum, UserInfoControlPresenter.getToken())
.subscribeOn(Schedulers.io())
.map(new ResponseFunc<>(new ResponseFunc.CallMe, String>() {
@Override
public List onCall(String data, String requestTime) {
return dataListHandler.String2DataList(data);
}
}))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BaseSubscribers>(refreshView) {
@Override
public void onCompleted() {
///< 如果是刷新才调用刷新结束接口
if (_bIsRefresh){
if (1 == _pageNum){
refreshView.finishRefresh();
}
else{
refreshView.finishLoadMore();
}
}
else{ ///< @首次请求, 不是刷新,取消进度条
refreshView.disDialog();
}
}
@Override
public void onErrors(ExceptionHandle.ResponeThrowable responeThrowable) {
///< 接下来就可以根据状态码进行处理...
int statusCode = responeThrowable.code;
switch (statusCode) {
case ExceptionHandle.ERROR.TOKEN:
UserInfoControlPresenter.clearAcount();
refreshView.showToast("你的账号异常,请重新登录,谢谢!");
break;
default:
refreshView.showToast(responeThrowable.message);
break;
}
if (!_bIsRefresh){
refreshView.retryDialog();
}
else{
refreshView.onRequestFailer();
}
onCompleted();
}
@Override
public void onNext(List dataList) {
if (dataList.size() < 1){
if (1 == _pageNum){ ///< @再次请求首页如果没有数据的情况下,清空列表
refreshView.resetItemList();
refreshView.onSucess(dataList);
}
else{
refreshView.showToast("沒有糖果了!");
}
}else{
if (1 == _pageNum){
refreshView.resetItemList();
refreshView.onSucess(dataList);
}
else{
refreshView.onSucess(dataList);
}
}
}
});
subscriptionList.add(subscription);
}
@Override
public void releaseResource() {
for (int i = 0; i < subscriptionList.size(); ++i){
if (null != subscriptionList.get(i) && !subscriptionList.get(i).isUnsubscribed()) {
subscriptionList.get(i).unsubscribe();
}
}
subscriptionList.clear();
}
/*
*@Description: JSON数据处理回调 - 调用者进行处理
*@Author: hl
*@Time: 2018/11/21 16:44
*/
public interface DataListHandler{
List String2DataList(String strData); ///< JSON字符串转换为对象列表返回
}
public interface DataHandler{
D String2Data(String strData); ///< JSON字符串转换为对象返回
}
}
BaseControlContract.java
import java.util.HashMap;
import java.util.List;
/*
*@Description: 服务+视图层的纽带
*@Author: hl
*@Time: 2018/11/21 13:55
*/
public interface BaseControlContract {
/**
* 负责设置界面
*/
interface View extends BaseView{
void onSucess(T t);
}
interface RefreshView extends BaseViewByRefresh{
void onSucess(List listT);
}
/**
* 负责请求网络获取数据
*/
interface Presenter extends BasePresenter{
/**
* 请求数据【对象】
* @param _funUrl
* @param _paramList
*/
void requestData(final String _funUrl, HashMap _paramList);
/**
* 请求数据【对象】列表
* @param _funUrl
* @param _pageNum
* @param _bIsRefresh
*/
void requestDataList(final String _funUrl, int _pageNum, boolean _bIsRefresh);
}
}
BaseService.java
import com.x.finance.net.HttpResponse;
import java.util.HashMap;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Url;
import rx.Observable;
/*
*@Description: 服务请求方法
*@Author: hl
*@Params:
* D - data对象、实体类、字符串....
*@Time: 2018/11/21 12:02
*/
public interface BaseService{
@GET ///< GET方法 - 获取数据【对象】
Observable> getData(@Url String url, @QueryMap HashMap paramMap);
@GET ///< GET方法 - 获取数据【对象】列表
Observable> getDataList(@Url String url,
@Query("page") int pageNum,
@Query("access_token") String access_token);
@FormUrlEncoded
@POST ///< POST方法 - 获取数据【对象】
Observable> postData(@Url String url, @FieldMap HashMap paramMap);
}
使用:
成功回调的地方:
小白的BaseViewByRefresh是基于BaseView的
BaseView.java
/**
* View负责显示数据,被Presenter调用来设置界面,可以是Activity, Fragment,或者View, Dialog
* Created by hl on 2018/3/13.
*/
public interface BaseView {
/**
* 共有的一些UI操作,比如吐司,进度条显示,消失等
*/
void showDialog();
void disDialog();
void retryDialog();
void emptyDialog();
void showToast(String msg);
void showRunToast(String msg);
}
BaseViewByRefresh.java
/**
* View负责显示数据,被Presenter调用来设置界面,可以是Activity, Fragment,或者View, Dialog
* Created by hl on 2018/3/13.
*/
public interface BaseViewByRefresh extends BaseView{
/**
* 结束下拉刷新
*/
void finishRefresh();
/**
* 结束上拉加载刷新
*/
void finishLoadMore();
/**
* 重置列表
*/
void resetItemList();
/**
* 请求失败
*/
void onRequestFailer();
}
大量的接口啥的....再结合泛型搞一搞...有些要结合之前的一些总结。然后逐步完善才行。
就先记录到这里吧。。后面再看看怎么完善,小白都不知道这样到底合不合理,哈哈.....
下班了,希望天天坚持,天天开心 - 黄磊