律师个人网站有用吗,企业在什么网站推广,专业制作网站电脑,上海做网站去哪里Retrofit 除了提供了传统的 Callback 形式的 API#xff0c;还有 RxJava 版本的 Observable 形式 API。下面我用对比的方式来介绍 Retrofit 的 RxJava 版 API 和传统版本的区别。
以获取一个 User 对象的接口作为例子。使用Retrofit 的传统 API#xff0c;你可以用这样的方式…Retrofit 除了提供了传统的 Callback 形式的 API还有 RxJava 版本的 Observable 形式 API。下面我用对比的方式来介绍 Retrofit 的 RxJava 版 API 和传统版本的区别。
以获取一个 User 对象的接口作为例子。使用Retrofit 的传统 API你可以用这样的方式来定义请求
GET(/user)
public void getUser(Query(userId) String userId, CallbackUser callback);
在程序的构建过程中 Retrofit 会把自动把方法实现并生成代码然后开发者就可以利用下面的方法来获取特定用户并处理响应
getUser(userId, new CallbackUser() {Overridepublic void success(User user) {userView.setUser(user);}Overridepublic void failure(RetrofitError error) {// Error handling...}
};
而使用 RxJava 形式的 API定义同样的请求是这样的
GET(/user)
public ObservableUser getUser(Query(userId) String userId);
使用的时候是这样的
getUser(userId).observeOn(AndroidSchedulers.mainThread()).subscribe(new ObserverUser() {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 CallbackUser() {Overridepublic void success(User user) {processUser(user); // 尝试修正 User 数据userView.setUser(user);}Overridepublic void failure(RetrofitError error) {// Error handling...}
};
有问题吗
很简便但不要这样做。为什么因为这样做会影响性能。数据库的操作很重一次读写操作花费 10~20ms 是很常见的这样的耗时很容易造成界面的卡顿。所以通常情况下如果可以的话一定要避免在主线程中处理数据库。所以为了提升性能这段代码可以优化一下
getUser(userId, new CallbackUser() {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 Action1User() {Overridepublic void call(User user) {processUser(user);}).observeOn(AndroidSchedulers.mainThread()).subscribe(new ObserverUser() {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(CallbackString callback);GET(/user)
public void getUser(Query(token) String token, Query(userId) String userId, CallbackUser callback);...getToken(new CallbackString() {Overridepublic void success(String token) {getUser(token, userId, new CallbackUser() {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 ObservableString getToken();GET(/user)
public ObservableUser getUser(Query(token) String token, Query(userId) String userId);...getToken().flatMap(new Func1String, ObservableUser() {Overridepublic ObservableUser onNext(String token) {return getUser(token, userId);}).observeOn(AndroidSchedulers.mainThread()).subscribe(new ObserverUser() {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) ObservableJsonObject 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操作实例 - 简书