Retrofit 除了提供了传统的 Callback 形式的 API,还有 RxJava 版本的 Observable 形式 API。下面我用对比的方式来介绍 Retrofit 的 RxJava 版 API 和传统版本的区别。

以获取一个 User 对象的接口作为例子。使用Retrofit 的传统 API,你可以用这样的方式来定义请求:

@GET("/user")
public void getUser(@Query("userId") String userId, Callback<User> callback);

在程序的构建过程中, Retrofit 会把自动把方法实现并生成代码,然后开发者就可以利用下面的方法来获取特定用户并处理响应:

getUser(userId, new Callback<User>() {@Overridepublic void success(User user) {userView.setUser(user);}@Overridepublic void failure(RetrofitError error) {// Error handling...}
};

而使用 RxJava 形式的 API,定义同样的请求是这样的:

@GET("/user")
public Observable<User> getUser(@Query("userId") String userId);

使用的时候是这样的:

getUser(userId).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<User>() {@Overridepublic void onNext(User user) {userView.setUser(user);}@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable error) {// Error handling...}});

看到区别了吗?

当 RxJava 形式的时候,Retrofit 把请求封装进 Observable ,在请求结束后调用 onNext() 或在请求失败后调用 onError()。

对比来看, Callback 形式和 Observable 形式长得不太一样,但本质都差不多,而且在细节上 Observable 形式似乎还比 Callback 形式要差点。那 Retrofit 为什么还要提供 RxJava 的支持呢?

因为它好用啊!从这个例子看不出来是因为这只是最简单的情况。而一旦情景复杂起来, Callback 形式马上就会开始让人头疼。比如:

假设这么一种情况:你的程序取到的 User 并不应该直接显示,而是需要先与数据库中的数据进行比对和修正后再显示。使用 Callback 方式大概可以这么写:

getUser(userId, new Callback<User>() {@Overridepublic void success(User user) {processUser(user); // 尝试修正 User 数据userView.setUser(user);}@Overridepublic void failure(RetrofitError error) {// Error handling...}
};

有问题吗?

很简便,但不要这样做。为什么?因为这样做会影响性能。数据库的操作很重,一次读写操作花费 10~20ms 是很常见的,这样的耗时很容易造成界面的卡顿。所以通常情况下,如果可以的话一定要避免在主线程中处理数据库。所以为了提升性能,这段代码可以优化一下:

getUser(userId, new Callback<User>() {@Overridepublic void success(User user) {new Thread() {@Overridepublic void run() {processUser(user); // 尝试修正 User 数据runOnUiThread(new Runnable() { // 切回 UI 线程@Overridepublic void run() {userView.setUser(user);}});}).start();}@Overridepublic void failure(RetrofitError error) {// Error handling...}
};

性能问题解决,但……这代码实在是太乱了,迷之缩进啊!杂乱的代码往往不仅仅是美观问题,因为代码越乱往往就越难读懂,而如果项目中充斥着杂乱的代码,无疑会降低代码的可读性,造成团队开发效率的降低和出错率的升高。

这时候,如果用 RxJava 的形式,就好办多了。 RxJava 形式的代码是这样的:

getUser(userId).doOnNext(new Action1<User>() {@Overridepublic void call(User user) {processUser(user);}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<User>() {@Overridepublic void onNext(User user) {userView.setUser(user);}@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable error) {// Error handling...}});

其中

doOnNext()的执行在onNext()之前,对数据进行相关处理。doOnNext在哪一个线程处理,暂时不明。

参考链接

RxJava操作符doOnNext - 享受技术带来的快乐! - 博客频道 - CSDN.NET

Rxjava中的doOnNext的作用和在哪里执行 - u010746364的博客 - 博客频道 - CSDN.NET

后台代码和前台代码全都写在一条链中,明显清晰了很多。

再举一个例子:假设 /user 接口并不能直接访问,而需要填入一个在线获取的 token ,代码应该怎么写?

Callback 方式,可以使用嵌套的 Callback:

@GET("/token")
public void getToken(Callback<String> callback);@GET("/user")
public void getUser(@Query("token") String token, @Query("userId") String userId, Callback<User> callback);...getToken(new Callback<String>() {@Overridepublic void success(String token) {getUser(token, userId, new Callback<User>() {@Overridepublic void success(User user) {userView.setUser(user);}@Overridepublic void failure(RetrofitError error) {// Error handling...}};}@Overridepublic void failure(RetrofitError error) {// Error handling...}
});

倒是没有什么性能问题,可是迷之缩进毁一生,你懂我也懂,做过大项目的人应该更懂。

而使用 RxJava 的话,代码是这样的:

@GET("/token")
public Observable<String> getToken();@GET("/user")
public Observable<User> getUser(@Query("token") String token, @Query("userId") String userId);...getToken().flatMap(new Func1<String, Observable<User>>() {@Overridepublic Observable<User> onNext(String token) {return getUser(token, userId);}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<User>() {@Overridepublic void onNext(User user) {userView.setUser(user);}@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable error) {// Error handling...}});

用一个 flatMap() 就搞定了逻辑,依然是一条链。看着就很爽,是吧?

RxJava配合Retrofit2.0使用

新的Retrofit2.0简直就是设计模式的教科书典范,同时对Rx的支持也更加友好,本例子为查询ip获取地理信息,并过滤掉失败信息

//使用Rxjava配合Retrofit解析json数据,注意这里全是电脑运行的,没有分开线程订阅
public static void main(String[] args) throws Exception{
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LoggingInterceptor());//log for okhttpRetrofit retrofit = new Retrofit.Builder().baseUrl(IPService.END).client(client).addConverterFactory(GsonConverterFactory.create())//对Response进行adapter转换.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//对转换后的数据进行再包装.build();retrofit.create(IPService.class)//动态代理生成class//直接操作json数据,这里可不是一个好的习惯,真正应该是DTO对象的.getIPInfo("58.19.239.11").filter(jsonObject -> jsonObject.get("code").getAsInt()==0)//转换数据类型.map(jsonObject1 -> jsonObject1.get("data"))//输出结果.subscribe(System.out::println);
}//retrofit定义的接口
interface IPService {String END = "http://ip.taobao.com";//建议写成dto对象,博主只是为了演示filter就把这里JsonObject了@GET("/service/getIpInfo.php") Observable<JsonObject> getIPInfo(@Query("ip") String ip);
}/**
* Retrofit2.0已经把网络部分剥离了,所以需要自己实现Log
*/
static class LoggingInterceptor implements Interceptor {@Override public Response intercept(Chain chain) throws IOException {Request request = chain.request();long t1 = System.nanoTime();System.out.println(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(),request.headers()));Response response = chain.proceed(request);long t2 = System.nanoTime();System.out.println(String.format("Received response for %s in %.1fms%n%s", response.request().url(),(t2 - t1) / 1e6d, response.headers()));return response;
}

源代码

rengwuxian RxJava Samples

参考链接

给 Android 开发者的 RxJava 详解

函数式编程RxJava操作实例 - 简书

Retrofit与RXJava整合相关推荐

  1. 使用Retrofit和RxJava

    使用Retrofit和RxJava整合访问网络,然后将数据显示到界面上 def retrofitVersion = '2.0.0-beta1'dependencies {compile fileTre ...

  2. java中使用okhttpsoap,Android okHttp网络请求之Retrofit+Okhttp+RxJava组合

    Retrofit介绍: Retrofit和okHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库,Retrofit简化了网络请求流程,基于OkHtttp做了封装,解耦的更彻底:比 ...

  3. retrofit与rxjava使用

    retrofit和rxjava(加深) http://www.jianshu.com/p/64af68c5638c Android Retrofit + RxJava使用详解(基础) http://w ...

  4. Java游戏碟中谍,煮 Retrofit 论 RxJava(一)

    首先,本篇是基于这个的总结.思考和拓展,那篇作者由浅入深,徐徐道来,读起来感觉很棒. ** 1.使用Retrofit来进行网络请求 ** a.网络接口使用豆瓣电影的top250,我们根据它返回的jso ...

  5. Retrofit+OKHttp+RxJava的使用

    什么是响应式编程   响应式编程是一种基于异步数据 流概念的编程模式.数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一 条流合并为一条新的流. 什么是RxJava RxJava ...

  6. 解决Retrofit和RxJava 抛出异常报错问题

    解决Retrofit和RxJava 抛出异常报错问题 package com.dingtao.rrmmp.core.exception;public class ApiException extend ...

  7. Android Retrofit使用教程(三):Retrofit与RxJava初相逢

    上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用. 了解RxJava RxJava有种种好处,我不在这里一一讲述.这里我只给 ...

  8. java okhttp3 工具类,Retrofit+okhttp+Rxjava网络请求工具类

    1.BaseApis接口封装请求方式 package com.example.wdshop.network; import java.util.Map; import okhttp3.Response ...

  9. ACCU天气API以及Okhttp、Retrofit、RxJava的使用

    因为公司项目需要使用到天气信息,而且有国外的使用需求,所以就没有选择国内的信息提供商,而是把目光瞄向了国际化的 ACCUWeather.通过下面的两个链接,我们可以简单的了解到AccuWeather的 ...

最新文章

  1. 可逼近信道容量编码技术之霍夫曼编码的实现
  2. SpringBoot初体验
  3. 【干货】极简体验+免费真的万能嘛?北森Saas第一坑:免费
  4. python中字典的几种定义方式
  5. PHP中的json_encode和json_decode
  6. NDK建立多个共享库
  7. CV_Sicong Liu
  8. 【2021.01.01】人生中很重要的一个十年,差强人意
  9. STM32F7xx —— ADC
  10. HONGJIN4 2013
  11. Java编译的运行机制初步讲解
  12. 百度地图的一个有价值的应用
  13. 马化腾:整天在拍拍网上买东西,找感觉
  14. (11)数据分析-TableOne工具
  15. 谷歌浏览器任务栏图标变白色解决方法
  16. ASP.NET4.0尚未在Web服务器上注册
  17. 拓嘉辰丰:拼多多限时折扣怎样设置?注意事项
  18. html img 拉伸,图片因img标签拉伸的处理办法
  19. VB.NET的 结构和类
  20. 自动驾驶软件开发人才现状_新技术改变传统出行方式 多国自动驾驶行业现状及人才需求分析...

热门文章

  1. 深度解析LSTM神经网络的设计原理
  2. 去腾讯等BAT面试完的Mysql面试55题总结,含答案大赠送!
  3. 会议交流 | 如何将图谱实体与关系更好的向量化,并基于推理扩充知识边界?——DataFun Summit2022知识图谱在线峰会...
  4. 论文浅尝 - TACL2020 | TYDI QA:Google 发表一个多语言的问答语料库
  5. 论文浅尝 | AMUSE: 基于 RDF 数据的多语言问答语义解析方法
  6. 王仲远 | 基于概念知识图谱的短文本理解
  7. 常见中文NER数据集大盘点
  8. Kubernetes 1.20 版本开始将弃用 Docker,是时候拥抱 Containerd 和 Podman 了!
  9. 干货 | 深度学习的可解释性研究(一):让模型「说人话」
  10. 【NLP】Google BERT详解