作者简介

本篇来自 小河马 的投稿,分享了自己是如何进行 RxJava+Retrofit 的封装。本文的技术点自然没话说,另外对于这种模块化的思路,希望能帮助到大家。最后提前祝大家周末愉快以及圣诞快乐!

小河马 的博客地址:

http://www.jianshu.com/users/14354bcb0e09

前言

Retrofit 和 RxJava 已经出来很久了,很多前辈写了很多不错的文章,在此不得不感谢这些前辈无私奉献的开源精神,能让我们站在巨人的肩膀上望得更远。对于 RxJava 不是很了解的同学推荐你们看扔物线大神的这篇文章:

给Android开发者的RxJava详解

http://gank.io/post/560e15be2dca930e00da1083

一遍看不懂就看第二遍。Retrofit的使用可以参考:

Android Retrofit2.0使用

http://wuxiaolong.me/2016/01/15/retrofit

本文内容是基于 Retrofit + RxJava 做的一些巧妙的封装。参考了很多文章加入了一些自己的理解,请多指教。源码地址:

https://github.com/Hemumu/RxSample

先放出 build.gradle

本文是基于 RxJava1.1.0 和 Retrofit 2.0.0-beta4 来进行的。

初始化Retrofit

新建类Api,此类就是初始化 Retrofit,提供一个静态方法初始化 Retrofit 非常简单.

提供一个静态方法初始化 Retrofit,手动创建了 OkHttpClient 设置了请求的超时时间。并在 OkHttp 的拦截器中增加了请求头。注意这里是为所有的请求添加了请求头,你可以单独的给请求增加请求头,例如:

和 Retrofit 初始化不同的地方就在我们添加了这两句话:

和 Retrofit 初始化不同的地方就在我们添加了这两句话:

变成了:

返回值变成了 Observable,这个 Observable 不就是 RxJava 的可观察者(即被观察者)么。

封装服务器请求以及返回数据

用户在使用任何一个网络框架都只关心请求的返回和错误信息,所以对请求的返回和请求要做一个细致的封装。

我们一般请求的返回都是像下面这样:

如果你们的服务器返回不是这样的格式那你就只有坐下来请他喝茶,跟他好好说(把他头摁进显示器)了。大不了就献出你的菊花吧!

对于这样的数据我们肯定要对 code 做出一些判断,不同的 code 对应不同的错误信息。所以我们新建一个 HttpResult 类,对应上面的数据结构。

这算是所有实体的一个基类,data 可以为任何数据类型。

我们要对所以返回结果进行预处理,新建一个 RxHelper,预处理无非就是对 code 进行判断和解析,不同的错误返回不同的错误信息,这还不简单。Rxjava 的 map 操作符不是轻松解决。

哟,这不是轻松愉快 so seay么!对 code 进行了判断,code 为0 就做对应更新UI或者其他后续操作,不等于0就抛出异常,在 ApiException 中对 code 做处理,根据 message 字段进行提示用户。

然而。。。RxJava 永远比你想象的强大。RxJava 中那么多操作符看到我身体不适,有个操作符 compose。因为我们在每一个请求中都会处理 code 以及一些重用一些操作符,比如用 observeOn 和 subscribeOn 来切换线程。

RxJava提供了一种解决方案:Transformer(转换器),一般情况下就是通过使用操作符Observable.compose()来实现。具体可以参考:

避免打断链式结构:使用.compose( )操作符

http://www.jianshu.com/p/e9e03194199e

新建一个 RxHelper 对结果进行预处理,代码:

Transformer 实际上就是一个 Func1<Observable<T>, Observable<R>>,换言之就是:可以通过它将一种类型的 Observable 转换成另一种类型的 Observable,和调用一系列的内联操作符是一模一样的。

这里我们首先使用 flatMap 操作符把 Obserable<HttpResult<T>>,转换成为 Observable<T> 在内部对code 进行了预处理。如果成功则把结果 Observable<T> 发射给订阅者。反之则把 code 交给 ApiException 并返回一个异常,ApiException 中我们对 code 进行相应的处理并返回对应的错误信息。

最后调用了频繁使用的 subscribeOn() 和 observeOn() 以及 unsubscribeOn()

处理ProgressDialog

在 Rxjava 中我们什么时候来显示 Dialog 呢。一开始觉得是放在 Subscriber<T> 的 onStart 中。onStart 可以用作流程开始前的初始化。然而  onStart() 由于在subscribe() 发生时就被调用了,因此不能指定线程,而是只能执行在  subscribe() 被调用时的线程。所以 onStart 并不能保证永远在主线程运行。

怎么办呢?

千万不要小看了 RxJava,与 onStart() 相对应的有一个方法 doOnSubscribe(),它和  onStart() 同样是在 subscribe() 调用后而且在事件发送前执行,但区别在于它可以指定线程。默认情况下,doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。

可以看到在 RxHelper 中看到我们调用了两次 subscribeOn,最后一个调用也就是离doOnSubscribe() 最近的一次 subscribeOn 是指定的 AndroidSchedulers.mainThread() 也就是主线程。这样我们就就能保证它永远都在主线运行了。这里不得不感概 RxJava 的强大。

这里我们自定义一个类 ProgressSubscriber 继承 Subscriber<T>

初始化 ProgressSubscriber 新建了一个我们自己定义的 ProgressDialog 并且传入一个自定义接口 ProgressCancelListener。此接口是在 SimpleLoadDialog 消失 onCancel 的时候回调的。用于终止网络请求。

ProgressSubscriber 其他就很简单了,在 onCompleted() 和 onError() 的时候取消 Dialog。需要的时候调用 showProgressDialog 即可。

处理数据缓存

服务器返回的数据我们肯定要做缓存,所以我们需要一个 RetrofitCache 类来做缓存处理。

几个参数注释上面已经写得很清楚了,不需要过多的解释。这里我们先取了一个 Observable<T> 对象 fromCache,里面的操作很简单,去缓存里面找个 key 对应的缓存,如果有就发射数据。

在 fromNetwork 里面做的操作仅仅是缓存数据这一操作。最后判断如果强制刷新就直接返回 fromNetwork反之用 Observable.concat() 做一个合并。concat 操作符将多个 Observable 结合成一个 Observable并发射数据。这里又用了 first()fromCache 和 fromNetwork 任何一步一旦发射数据后面的操作都不执行。

最后我们新建一个 HttpUtil 用来返回用户关心的数据,缓存,显示Dialog在这里面进行:

Activity生命周期管理

基本的网络请求都是向服务器请求数据,客户端拿到数据后更新UI。但也不排除意外情况,比如请求回数据途中 Activity 已经不在了,这个时候就应该取消网络请求。

要实现上面的功能其实很简单,两部分

  • 随时监听 Activity(Fragment) 的生命周期并对外发射出去; 在我们的网络请求中,接收生命周期

  • 并进行判断,如果该生命周期是自己绑定的,如 Destory,那么就断开数据向下传递的过程

实现以上功能需要用到 Rxjava 的 Subject 的子类 PublishSubject

在你的 BaseActivity 中添加如下代码:

这样的话,我们把所有生命周期事件都传给了 PublishSubject 了,或者说 PublishSubject 已经接收到了并能够对外发射各种生命周期事件的能力了。

现在我们要让网络请求的时候去监听这个 PublishSubject,在收到相应的生命周期后取消网络请求,这又用到了我们神奇的 compose(),我们需要修改 handleResult 代码如下:

调用的时候增加了两个参数一个是 ActivityLifeCycleEvent 其实就是一些枚举表示 Activity 的生命周期

public enum ActivityLifeCycleEvent {
   CREATE,
   START,
   RESUME,
   PAUSE,
   STOP,
   DESTROY
}

另外一个参数就是我们在 BaseActivity 添加的 PublishSubject,这里用到了 takeUntil(),它的作用是监听我们创建的 compareLifecycleObservable

compareLifecycleObservable 中就是判断了如果当前生命周期和 Activity 一样就发射数据,一旦compareLifecycleObservable 对外发射了数据,就自动把当前的Observable(也就是网络请求的Observable)停掉。

当然有个库是专门针对这种情况的,叫

RxLifecycle

https://github.com/trello/RxLifecycle

不过要继承他自己的 RxActivity,当然这个库不只是针对网络请求,其他所有的Rxjava都可以。有需要的可以去看看。

最后新建一个 ApiService 存放我们的请求:

使用起来就超级简单了:

具体很多东西都可以在使用的时候具体修改,比如缓存我用的 Hawk。Dialog 是我自己定义的一个 SimpleLoadDialog。源码已经给出请多指教!

Android RxJava+Retrofit完美封装的更多相关文章

  1. RxJava+Retrofit+OkHttp,一步一步封装网络框架;

    使用RxJava+Retrofit+OkHttp,首先在build.gradle添加: compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com ...

  2. android打飞机游戏、MVP句子迷App、悬浮窗、RxJava+Retrofit、加载动画、定制计划App等源码

    Android精选源码 微信打飞机 android进度设置加载效果源码 Android新手引导库EasyGuide MVP-好看又好用的句子迷客户端 XFloatView 一个简易的悬浮窗实现方案 a ...

  3. 【知识必备】RxJava+Retrofit二次封装最佳结合体验,打造懒人封装框架~

    一.写在前面 相信各位看官对retrofit和rxjava已经耳熟能详了,最近一直在学习retrofit+rxjava的各种封装姿势,也结合自己的理解,一步一步的做起来. 骚年,如果你还没有掌握ret ...

  4. android完整资讯App、Kotlin新闻应用MVP + RxJava + Retrofit + Dagger2、优雅区间选择器等源码

    Android精选源码 Android完整资讯客户端源码 android展示注册进度效果源码 Android Wifi热点数据传输Socket 通信示例源码 Android Dota的辅助信息app源 ...

  5. android流式布局、待办事项应用、贝塞尔曲线、MVP+Rxjava+Retrofit、艺术图片应用等源码

    Android精选源码 android模仿淘宝首页效果源码 一款艺术图片应用,采用T-MVVM打造 Android MVP + RxJava + Retrofit项目 android流式布局实现热门标 ...

  6. Rxjava + retrofit + dagger2 + mvp搭建Android框架

    最近出去面试,总会被问到我们项目现在采用的什么开发框架,不过据我的经验网络框架(volley)+图片缓存(uIl)+数据库(orm)+mvp,不过现在这套框架比较好了,现在采用什么呢?Rxjava + ...

  7. RxJava + Retrofit 的实际应用场景

    关于 RxJava Retrofit 很多篇文章都有详细的说明,在这里我想分享一个具体的使用案例,在我的开源项目 就看天气 里的实际应用.也希望跟大家探讨如何优雅的使用. 准备 项目中用到的依赖: c ...

  8. RxJava + Retrofit完成网络请求

    1.前言 本文基于RxJava.Retrofit的使用,若是对RxJava或Retrofit还不了解的简友可以先了解RxJava.Retrofit的用法再来看这篇文章. 在这片文章之前分别单独介绍过R ...

  9. Android开发 retrofit入门讲解

    前言 retrofit基于okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.如果你不了解OKhttp建议你还是先了解它在来学习 ...

随机推荐

  1. SQL Function 自定义函数

    目录 产生背景(已经有了存储过程,为什么还要使用自定义函数) 发展历史 构成 使用方法 适用范围 注意事项 疑问   内容 产生背景(已经有了存储过程,为什么还要使用自定义函数) 与存储过程的区别(存 ...

  2. iphoneX 适配

    1.iphoneX的尺寸  375*812   上边有44px的危险区,下边有34px的危险区,剩下的是安全区. 2.viewport设值cover <meta name="viewp ...

  3. python笔记09-----装饰器,生成器,迭代器

    1.装饰器 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器的知识储备: 1.      函数即“变 ...

  4. Linux内存信息查看——free命令

    free 命令可以显示系统已用和空闲的内存情况.包括物理内存.交互区内存(swap)和内核缓冲区内存(buffer).共享内存将被忽略.在Linux系统监控的工具中,free命令是最经常使用的命令之一 ...

  5. 【LeetCode题解】206_反转链表(Reverse-Linked-List)

    目录 描述 解法一:迭代 思路 Java 实现 Python 实现 复杂度分析 解法二:递归 思路 Java 实现 Python 实现 复杂度分析 更多 LeetCode 题解笔记可以访问我的 git ...

  6. FSM有限状态机

    1.什么是有限状态机 有限状态机(Finite State Machine),简称FSM,它由一组有限个状态.输入和根据输入及现有状态转换为下一个状态的转换函数组成,当然,通常每个状态机都必须有一个初 ...

  7. JavaScript预编译详解

    一.js运行三部曲: 1.语法分析(通篇扫描看有没有语法错误) 2.预编译 3.解释执行 二.预编译前奏 1.imply global 暗示全局变量:任何变量如果未经声明就赋值,此变量为全局对象所有 ...

  8. mysql 中文乱码 解决

    数据库安装设置编码: mysql默认的字符编码是latin1,而我用的是utf-8,存入数据库就变成了?????这样的乱码,解决方法:   修改安装路径下的my.ini文件,default-chara ...

  9. 【手记】解决VS2010宏功能报错

    抱歉问题解决前没留截图,总之就是使用宏相关的功能都打不开,会弹窗报错,英文,大意是[一个或多个组件不存在,请尝试重装]. 尝试过: 修复安装VS2010 按此文照做:https://visualstu ...

  10. 使用 ahk 让普通键盘变为Dvorak键盘

    本文告诉大家,如何使用软件做出Dvorak键盘. 在开始说如何做之前,需要告诉大家,什么是Dvorak键盘. Dvorak Simplified Keyboard /ˈdvɔːræk, dəˈvɔː- ...