眼下Retrofit+RxJava搭配的网络请求框架非常流行,本着学习的态度,写了一个相关的demo。写着写着就想朝着搭建一个项目框架的方向走。因而使用了一下MVP模式。git
RxJava 确实挺好用,我的特别喜欢这种“流式”的代码风格,逻辑很清晰,起码提供了一种相对的规范,开发者按照对应的流程写代码,后期的维护和拓展会简单不少。github
MVP模式简单说就是为了解耦,各行各职,阅读代码,拓展功能代价不会那么大(或许有些人认为不必用MVP,直接在activity/fragment中写代码就行了,那只能说你没遇到到过相对大一点的项目,或者没遇到“实习生”写代码,那酸爽,看代码会看得你怀疑人生)服务器
在使用MVC开发Android应用的时候,原理上网络
可是写代码的时候,你就会发现,好多跟view相关的操做都在activity中实现完成了,致使activity既是Controllor又是View,网上有人称为是MV模式,也所以致使activity的代码量特别大,1000+的代码很常见
后来,Presenter的出现,将Actvity,xml 视为View层,Model不变,Presenter负责完成View层与Model层的交互。因而MVP是这样的:架构
在网上看了一下MVP的使用demo,挺多人将一个页面须要完成的操做,以及须要用到的控件所有定义到相关的View接口中,示例:框架
我的以为,这个有点蛋疼
1.这样view接口须要的方法太多了,有些实现(clearUserName())能够放在activity中操做,第一不需将控件经过接口传到Presenter中,第二我认为这种算是对View的操做,仍是能够看做View相关的。
2.咱们很难知道一个界面都要实现些什么方法(若是包括对某个控件内容清空等),可是咱们不难知道一个activity须要实现哪些主要的功能,好比登陆页面就一个登陆功能,或者再加多一个第三方登陆咯。函数
因此我以为View接口中定义一些经常使用的方法,以及一些须要实现的方法就能够了,经过回调内容,把控件赋值,数据展现等仍是放回在activity中操做,presenter只须要将对应的实体或者数据给activity就行了,activity怎么展现,不用管,不关个人事情,作到各行各职。工具
或许有人会说,咦~你这都不是MVP,网上的MVP这些操做要放在presenter中的,这时我上去就给你一巴掌,咱们使用优秀的框架/架构是为了学习它优秀的模式或者编码风格,若是一味的循序渐进照着用,那将毫无心义!同时,咱们只有不断改进,不断推成出新才能使得技术不断进步,若是前人不对MCV提出质疑,就不会有今天的MVP。布局
因此我以为View的接口应该这样
一个BaseView,定义经常使用的方法,其余页面View接口继承基类单元测试
这个基类怎么写看项目须要,按照开发者各自需求编写。
如今写一个登陆的LoginView,继承BaseView同时添加特定的接口
这里定义一个showResult(UserBean bean)
将User实体类传给activity,用于展现用户信息。
写到这里的时候的我突然更加坚决我所理解的MVP是对的,解耦嘛
Presenter:负责获取或者构建UserBean
Activity:负责展现Presenter给过来的数据
以前看到过有人经过View接口将activity的控件几乎“拷贝”到了presenter中,虽然实现了逻辑处理在Presenter,可是若是Presenter逻辑改动仍是会牵一发动全身,要改动不少
如今这种方式挺好的,负责构建数据,不参与展现,也方便单元测试。对,就是这样的。
Retrofit+RxJava确实是一种很不错的搭配,RxJava能够指定运行的线程,在网络请求时,开启线程耗时操做,响应结果时切换为主线程操做UI。很是漂亮,代码风格也赞,我我的称为流式操做,从上到下一步步表明操做的主要逻辑,比起传统的迷之嵌套,迷之缩进好多了。
咱们知道RxJava使用订阅模式,若是没有及时取消订阅,会致使内存泄漏,这个是很是糟糕的行为,固然解决方式也很简单,在对应的生命周期取消订阅就好,不过我仍是怀着好奇之心Github一下,果真已经有人对此做出了贡献RxLifecycle
经过绑定生命周期能够很方便的管理订阅与取消订阅。
Github: https://github.com/trello/RxLifecycle
Retrofit+RxJava的使用仍是挺简单的,不过相对于你们已经用在项目的网络请求框架,它仍是须要进行加工的。好比说错误处理,配合RxLifecycle使用,以及不少人会问的,在MVP中使用的时候怎么取消订阅。
先看下最简单的使用
接口代码
使用代码
代码简介,清晰,构建请求参数,构建被观察者对象,以及传入一个观察者对象实现
订阅回调onSubscribe
也能够是开始的操做
成功回调onNext
失败回调onError
监听完成onComplete
或许开发者一眼就看出了onError
回调的对象是Throwable
这个不能忍啊,投入使用的框架确定得封装,那就从这里开始
在常见的网络请求框架中通常会有两个回调函数
定义onError
回调函数触发的场景是:1.异常2.错误
1.异常:请求异常,解析数据出错,网络异常等等
2.错误:某一次请求逻辑错误,(例如:登陆错误)
将上述两种状况交给onError
回调函数处理
在请求逻辑成功的时候触发一个onSuccess
函数。这样监听者就只须要两个函数,一个失败,一个成功,失败提示给用户,成功负责展现数据,跳转页面等
定义一个异常处理类ExceptionEngine
异常处理类中,都是常见的错误类型,咱们经过解析Throwable
转换成统一的错误类ApiException
这个类很是简单,一个状态码,一个错误信息,方便咱们开发调试。
不过仔细看代码的同窗会发现,ServerException
这个是什么鬼?“服务器返回的错误”?Throwable
怎么知道这个错误类型是ServerException
?
其实这个ServerException
是咱们自定义的错误类型,通常咱们开发中都会跟服务器约定一种接口请求返回的数据。好比:
那么咱们就能够在解析服务端返回数据的时候,当code!=0,就抛出ServerException
OK,到这里咱们常见的错误类型,异常等都处理完了,经过ExceptionEngine
转化为统一的错误类型ApiException
,在订阅者回调onError(ApiException e)
就能够很方便知道错误的状态码以及对应的描述信息。
咱们使用onErrorResumeNext(new HttpResultFunction<>())
操做符对Retrofit网络请求抛出的Exception
进行处理,咱们定义HttpResultFunction
处理Retrofit抛出的Exception
,经过ExceptionEngine
转化为统一的错误类型ApiException
这一步是对错误,异常等的处理,若是某一个http请求没有发生异常,或者网络错误,就会走onNext
回调。
前面咱们约定,将服务器返回的逻辑错误也归类到onError
。因此咱们在.map(new ServerResultFunction())
操做符中处理服务器返回的结果是否正确(这里指逻辑正确,即code==0),若是code!=0,就抛出ServerException
解析服务器返回结果 HttpResponse
,这个类由开发者自行设置,根据实际状况来定义字段,这里我假设后台返回的字段有
String msg; int retCode; Object result;
这里Result
咱们使用Object
由于接口时通用的,服务端返回的接口类型也是多样的,多是列表
,也多是JSON
对象,或者String
字符串,因此这里咱们使用Object,在数据解析的时候在转化成为具体的类型
嗯,错误处理搞定了,那就是简单的封装一下Retrofit 和RxJava以及使用RxLifecycle
RxJava使用订阅模式,那咱们就须要封装一个被订阅者,一个订阅者,以及使用RxLifecycle自动管理订阅的生命周期
构建Api接口类
构建Retrofit工具类获取retrofit实例
构建网络请求(被订阅对象)
在HttpRxObservable
咱们构建一个被订阅者Observable
而且设置了错误处理,同时添加了生命周期管理。
处理订阅者Observer
使用网络请求的过程当中咱们确定会遇到取消请求的场景,这里咱们实现一个HttpRequestListener
,为每个请求添加惟一的TAG
用来标识具体的每个请求,开始请求时保存TAG,请求成功/失败移除标志,同时TAG也用作取消请求的标志。
编写一个测试类,示例如何使用Retrofit
使用RxLifecycle
管理订阅生命周期activity须要继承RxActivity
。开篇也提到MVP的时候,接下来就说说在MVP中如何使用。
定义一个Presenter基类
JAVA弱引用,管理View的引用,以及activity的引用,避免强引用致使资源没法释放而形成的内存溢出,
写代码的时候想到了一个很巧妙的方式:Presenter中传如一个activity,同时实现Activity生命周期监听,在onDestroy中移除View和Activity的引用,我的以为这个很是不错。看官能够客观评价一下优劣。
登陆Presenter
LoginActivity
以上是我对MVP的一点理解,以及对RxJava2+Retrofit2+RxLifecycle2进行的封装,因为编写demo的时候是朝着构建一个项目框架走的,因此没有贴完的代码就请移步到个人Github克隆完整版本,尽情的撸吧。
我的认为这个搭配仍是可行的,而且已经投入都项目中。好产品必定要本身先使用,承认。哈哈哈