使用RxJava优化Retrofit请求
来源:互联网 发布:ntp服务器配置 linux 编辑:程序博客网 时间:2024/05/17 00:53
使用RxJava优化Retrofit请求
在前几篇Google Drive相关的博客中,我们提到了token过期的问题。在进行任何一个Google APIs接口调用的时候,很有可能由于access token过期了(默认的使用期限才3600秒),会导致我们的请求失败,返回HTTP 401: Invalid Credentials error等异常。在这个时候,我们必须重新请求token,然后在请求成功的callback中再次请求我们相关的API。
看到这里,像这种异步的嵌套请求,我们很容易就联想到RxJava,异步世界必不可少的库。那么在Retrofit2.0中如何集成RxJava呢?在基于你已经正常使用Retrofit或者okhttp的情况下,只需简单3步,即可加入RxJava特性。
集成RxJava
Retrofit 2.0中加入了CallAdapter机制,官方已经准备好了几个CallAdapter module,其中最著名的module可能是为RxJava准备的CallAdapter
,它能将请求结果作为Observable
返回,而不是默认的Call
对象。
- Step1:对项目加入以下依赖:
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'compile 'io.reactivex:rxjava:1.1.3'compile 'io.reactivex:rxandroid:1.1.0'
- Step2:Retrofit Builder链表中加入
RxJavaCallAdapterFactory
Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
- Step3:修改Retrofit的网络请求接口,将返回Call改为返回Observable,现在你可以像操作RxJava中对象一样操作数据流了!
public interface DriveApi { @GET("oauth2/v3/userinfo") Observable<UserInfo> requestUserInfo( @Header("Authorization") String authToken);}
使用RxJava优化
根据上面的描述(以请求用户信息这个需求来做例子):当token失效时,请求会失败。此时我们需要重新请求token,然后再请求用户信息。这里能提取以下两点需求:
- 希望能够在请求用户信息失败时,自动请求token,并及时更新
- 希望能有重试次数限制,防止处于一直请求失败的死循环中
那么这两点在RxJava中能肿么实现呢?
- 在扔物线的RxJavaSamples里面认识到了retryWhen()这个操作符。它可以实现 token 失效时的自动重新获取,将 token 获取的流程彻底透明化,简化开发流程。
- 配合zipWith()和range(),可以实现失败重试的次数限制,防止无限重试。
对这3个操作符的原理和用法感兴趣的朋友可以直接进入链接深入学习,下面是经过RxJava优化过的代码(以请求用户信息这个为例子):
Observable.just(null) .flatMap(new Func1<Object, Observable<UserInfo>>() { @Override public Observable<UserInfo> call(Object o) { return mDriveApi.requestUserInfo(mToken.getAccessToken()); } }) .retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() { @Override public Observable<?> call(Observable<? extends Throwable> observable) { // Here we just retry 3 time return observable .zipWith(Observable.range(1, 3), new Func2<Throwable, Integer, Throwable>() { @Override public Throwable call(Throwable throwable, Integer integer) { return throwable; } }) .flatMap(new Func1<Throwable, Observable<?>>() { @Override public Observable<?> call(Throwable throwable) { if (throwable instanceof HttpException) { // Request token refresh if request UserInfo fail return mDriveApi.requestTokenRefresh(mToken.getRefreshToken(), CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN) .doOnNext(new Action1<Token>() { @Override public void call(Token token) { // Refresh the access token when get success mToken.setAccessToken(token.getAccessToken()); } }); } return Observable.just(throwable); } }); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<UserInfo>() { @Override public void call(UserInfo info) { // Handle the UserInfo here } });
下面简单解析上述流程:
当requestUserInfo()
抛出异常的时候,会进入到retryWhen()
包含的逻辑中。其中throwable Observable通过zipWith()
与Observable.range(1, 3)
生成的Observable组合在一起,以实现重试次数最多3次的限制。经过flatMap()
将requestTokenRefresh()
返回的Observable return。其中doOnNext()
操作符实现获取到token后将其更新至相应变量中,以使我们重新requestUserInfo()
时能用最新的token去请求数据。
有同学对一开始的Observable.just(null).flatMap()
可能不是太理解,因为token过期经过重试重新请求完回调时,会再次调用call()
方法重新执行requestUserInfo()
,并且此时call()
中传入的object每次都是同一个。若此处去掉flatMap()
,会导致一直使用旧的token进行请求,所以此处多加了一次flatMap()
包裹着。还是不理解的,可以把它去掉,自己对比下效果就明白了。
上面的代码用retrolambda
简化后可能逻辑会更清晰些。。。
- 使用RxJava优化Retrofit请求
- rxjava 和retrofit 结合使用 请求网络
- Rxjava+Retrofit 请求数据
- RXJava+Retrofit网络请求
- MVP +Retrofit +Rxjava 请求
- RxJAVA和Retrofit在安卓中网络请求使用实例
- Android使用RxJava+Retrofit请求网络的小Demo
- 初学者--Android Retrofit+RxJava+OkHttp使用post请求
- 使用Retrofit结合RxJava实现Get与Post网络请求
- MVP框架使用Retrofit+Rxjava请求网络数据
- RxJava + Retrofit完成网络请求
- Rxjava+Retrofit取消网络请求
- Retrofit+RxJava处理网络请求
- RxJava + Retrofit完成网络请求
- Retrofit+Rxjava请求工具类
- Retrofit+RxJava网络请求框架
- Retrofit+Rxjava完成网络请求
- Rxjava+Retrofit 简单使用
- 【机器学习入门——1】Python 开发环境的安装 Python(x,y)及Pycharm
- HDU5673 Robot DP 默慈金数 线性求1~n逆元 bestcoder
- MMC、SD等存储卡的区别总结
- 欧拉函数
- 稳定排序与不稳定排序方法
- 使用RxJava优化Retrofit请求
- mybatis知识点总结和梳理
- AndroidStudio中代码模板的使用
- 读取字体文件 模拟显卡点阵显示汉字
- Linux下软件常见安装方式
- 欢迎使用CSDN-markdown编辑器
- Cocoapads管理第三方库
- 打印二叉查找树所有满足k1<=key(x)<=k2的元素X
- 操作系统基础-下-进程控制及处理机调度