描述:17年最火的安卓网络框架无疑是Retrofit2.0+Okhttp3.0,而中型项目架构最火的无疑是MVP,而今年Rxjava2.0也是异常的火爆,而Rxlifecycle的支持对使用rxjava出现内存泄露问题得到完美解决,对此,之前楼主对这几种很火的技术封装过一次,现在根据业务增加,进行了二次封装。文章后面有本框架github地址。
一、所用技术
/ MVP 点击打开链接
/ Retrofit2.0 点击打开链接 点击打开链接
/ Okhttp3.0 点击打开链接
/ Rxjava2.0 点击打开链接
/ Rxlifecycle2.0 点击打开链接
这里就不细说这他们的基础知识了,传送门在上面。
二、架构
1.分包:目前demo里面涉及到的包如下,如有其他的需求自定义包的名字就好,比如adapter包、custom包。
主要作用如下图:
大家看到了上面这个多base想到了什么,基类?抽象?接口?继承?模版?答案是都对,不过还有一个没说到,那就是泛型。java语言有泛型的支持我觉得是一件很棒的事情,有了它我相信很多人都不用手动去写对象强转了吧。
1.BaseView类
public interface BaseView {
}
它里面为空,没有任何抽象方法,接口的作用有哪些还记得吗?其中有一个作用就是标识作用,标识它是一个View的基类。
2.BasePersenter
public abstract class BasePresenter{
private V mView;
public V getView(){
return mView;
}
public void attachView(V v){
mView = v;
}
public void detachView(){
mView = null;
}
}
其中泛型V继承于BaseView,也就是说我们传的V泛型是必须继承BaseView的,不然代码检查报错。我们可以看到attachView和detachView两个方法,当我们的view需要的时候就绑定p层,view销毁的时候就与p层解绑。
3.BaseModel
public class BaseModel {
/**
* 封装线程管理和订阅的过程
* flag 是否添加progressdialog
*/
public void subscribe(Context context, final Observable observable, ObserverResponseListener listener,
ObservableTransformer transformer, boolean isDialog, boolean cancelable) {
final Observer observer = new ProgressObserver(context, listener, isDialog,cancelable);
observable.compose(transformer)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
public void subscribe(Context context, final Observable observable, ObserverResponseListener listener,
ObservableTransformer transformer) {
subscribe(context,observable,listener,transformer,true,true);
}
}
BaseModel主要作用是封装线程管理和订阅的过程,当然也可以封装数据库的操作,这里我就没有写出来了。
4.BaseApi:
主要是封装网络对象retrofit,里面可以设置网络的连接超时和读取时间、日志拦截、缓存拦截、头文件拦截等等。
5.Api及ApiService:
主要管理api接口。
6.BaseActivity、BaseFragment
BaseActivity引用P和V,泛型有两个,必须分别继承与BaseView与BasePresenter。当子类activity继承于BaseAcivity时,getLayoutId方法获取绑定布局,然后createPresenter方法创建出p层,并将v视图绑定。然后调用的init方法,我们就可以将初始化数据放到这里。在activity销毁时,将p层与v视图解绑。Fragment用法也相似。
7.progress包:
ObserverResponseListener:请求监听成功或者失败。
ProgressCancelListener:请求监听取消时。
ProgressDialogHandler:dialog出现与隐藏的一个Handler。
ProgressObserver(观察者):继承与Observer,监听请求是否成功,
public class ProgressObserver implements Observer, ProgressCancelListener {
private static final String TAG = "ProgressObserver____ ";
private ObserverResponseListener listener;
private ProgressDialogHandler mProgressDialogHandler;
private Context context;
private Disposable d;
public ProgressObserver(Context context, ObserverResponseListener listener, boolean isDialog, boolean cancelable) {
this.listener = listener;
this.context = context;
if(isDialog){
mProgressDialogHandler = new ProgressDialogHandler(context, this, cancelable);
}
}
private void showProgressDialog() {
if (mProgressDialogHandler != null) {
mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
}
}
private void dismissProgressDialog() {
if (mProgressDialogHandler != null) {
mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
mProgressDialogHandler = null;
}
}
@Override
public void onSubscribe(Disposable d) {
this.d = d;
Log.e(TAG, "onSubscribe: ");
showProgressDialog();
}
@Override
public void onNext(T t) {
listener.onNext(t);//可定制接口,通过code回调处理不同的业务
}
@Override
public void onError(Throwable e) {
dismissProgressDialog();
Log.e(TAG, "onError: ", e);
//自定义异常处理
if(e instanceof ExceptionHandle.ResponeThrowable){
listener.onError((ExceptionHandle.ResponeThrowable)e);
} else {
listener.onError(new ExceptionHandle.ResponeThrowable(e, ExceptionHandle.ERROR.UNKNOWN));
}
if (e instanceof UnknownHostException) {
ToastUtil.showLongToast("请打开网络");
} else if (e instanceof SocketTimeoutException) {
ToastUtil.showLongToast("请求超时");
} else if (e instanceof ConnectException) {
ToastUtil.showLongToast("连接失败");
} else if (e instanceof HttpException) {
ToastUtil.showLongToast("请求超时");
}else {
ToastUtil.showLongToast("请求失败");
}
}
@Override
public void onComplete() {
dismissProgressDialog();
Log.e(TAG, "onComplete: ");
}
@Override
public void onCancelProgress() {
Log.e(TAG, "requestCancel: ");
//如果处于订阅状态,则取消订阅
if (!d.isDisposed()) {
d.dispose();
}
}
}
上面已经很清楚了,在onNext方法里面获取到响应再调用ObserverResponseListener接口的onNext回调到相应的P层,在观察者的onError方法里面根据自定义异常类,回调ObserverResponseListener接口的onError方法。自定义异常处理类就不多说了,里面很详细。这个观察者实现了ProgressCancelListener的onCancelProgress方法,也就是当我们点击回退键取消请求时,会调用此方法,在这里我们拿到将在onSubscribe时给我们的Disposable消费者对象取消消费事件,此时将不会下发事件到观察者的onNext方法,实现取消订阅。
到这里,本框架基本就结束了。
下面讲一下一个activity的例子:
1.创建契约类:为什么创建契约类?将一个业务所要用到的方法写在一起不是便于管理吗?以后需求增加或者改变,直接找契约类就行了。
V有三个方法:第一个是当数据请求成功时返回结果,第二个是失败时发送信息通知界面,第三个是绑定完成Observable发布的事件和当前组件绑定,实现生命周期同步,从而实现当前组件生命周期结束时,自动取消对Observable订阅。
P有一个方法:设置请求参数及是否显示dialog与该dialog是否能被取消。
2.创建实体类:这就不用说了。
3.创建model层:
我测试用的这个方法本来是想用我们公司的测试登录接口的,但是可能会改变,所以我就用的一个开源查询快递的api,可以直接使用通用的请求方法,故此直接继承BaseModel类,并调用subscribe这个方法即可。
4.创建Persenter层:
P层继承契约类里面写好的抽象P层,实现其中的login抽象方法,在P层构造中实例化M层对象。当P层的login方法被调用时,M层调用它自己的login方法进行网络请求。实现ObseriverResponseListener的请求成功与失败方法。当观察者走到了它的onNext方法时,它将会回调ObseriverResponseListener的onNext方法到P层,P层拿到数据结果,调用与之绑定的V层方法result传值给页面以更新数据,相应的onError方法也是如此理解即可。
5.activity页面:
如图所示:
页面只需要继承BaseActivity并传入业务逻辑相关的契约类V和P,然后实现接口V的方法。
大家应该理解得到,首先设置布局,创建该业务的P层实例,创建V层。然后就是等待按钮点击,调用P层的login方法,P层调用getview方法的bindlifecycle方法绑定生命周期,然后等待P层返回数据和Msg。
--->问题1:如何在一个页面实现多个请求
1.在Contract层的Presenter建立抽象方法2
2.在Module层建立方法,在ApiService层建立相应的接口;
3.在Activity实现Contract层的接口;
在Activity调用getPresenter().logout(map2,false,true),完成页面请求多个接口了。
--->问题2:业务量少的时候,不需要用P层的情况下,怎么使用rx来管理请求
1.创建Activity后继承BaseActivity,不需要传入泛型等等;
2.实现BaseActivity的createPresenter、createView方法时返回null,此时也需要一个module层来提供网络请求等的方法;
3.在Activity直接调用module层的方法进行请求即可。
以上例子是很简单的,在实际项目过程中,业务逻辑肯定相对复杂的多,不过大致的网络方面的问题基本上此框架即可完成。
阅读到此,本文也结束了,有问题请提问。坚持开源原则,源码放在github,希望不吝star哦,你的支持是我创作的动力。https://github.com/senonwx/mvpretrofitrx.git