Android RxJava/RxAndroid结合Retrofit使用
概述
RxJava是一个在 Java VM 上使用可观測的序列来组成异步的、基于事件的程序的库。更重要的是:使用RxJava在代码逻辑上会非常简洁明了,尤其是在复杂的逻辑上。告别迷之缩进。
RxAndroid是RxJava针对Android平台的拓展。
Retrofit是一个封装了okHttp的工具库。在上篇博文 Android 初探Retrofit2.0.1(最新版) 有过介绍,对Retrofit不太了解的读者,建议先行阅读。
RxJava GitHub地址:https://github.com/ReactiveX/RxJava
RxAndroid GitHub地址:https://github.com/ReactiveX/RxAndroid
Retrofit GitHub地址:https://github.com/square/retrofit
热身运动 - 观察者模式
RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。
以下简介下观察者模式。熟练掌握观察者模式可跳过这一小节。
观察者模式
如果如今有两个对象A和B。在A发生某种变化时要主动通知B。这就是观察者模式。
Android里View.setOnClickListener(new OnClickListener) 就是运用观察者模式的典型样例。在这个样例中View充当对象A的角色,OnClickListener充当B。View通过setOnClickListener将自己和OnClickListener联系(订阅)起来。当View捕获到点击事件之后,立刻调用OnClickListener#onClick() 方法。还有通常我们自定义的接口回调都是观察者模式的运用。
RxJava的观察者模式
RxJava基本概念:Observable (被观察者,相当于View)、 Observer (观察者,相当于OnClickListener)、 subscribe ()(订阅。相当于setOnClickListener()方法)事件。Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 能够在须要的时候发出事件来通知 Observer。
RxJava除了普通的回调方法onNext()还有onCompleted() 和 onError()。
- onCompleted():事件队列完结。
RxJava 不仅把每一个事件单独处理。还会把它们看做一个队列。没有新的onNext()之后,调用此方法。 
- onError():事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同一时候队列自己主动终止,不同意再有事件发出。
- onCompleted() 和 onError()在一个队列中仅仅能调用一个,而且是最后一个。onCompleted() 和 onError()还是相互排斥的,仅仅能调用当中一个
回想Retrofit
上篇博文我们使用Retrofit实现对网络的訪问以及返回数据的解析,详情请见Android 初探Retrofit2.0.1(最新版),在这里我们再简单温习下 
1. 创建WeatherInfoService,并制定请求数据的方式以及须要的查询參数 
2. 创建对应的WeatherInfoBean 
3. 创建Retrofit对象并使用GSON解析数据 
4. 调用 weatherInfoService#getWeatherInfo(FORMAT, CITYNAME, KEY),获取call 
5. 插入队列,并展示数据
RxJava/RxAndroid结合Retrofit
加入依赖
compile 'com.squareup.retrofit2:retrofit:2.0.1'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'io.reactivex:rxjava:1.1.0'
加入限权
<uses-permission android:name="android.permission.INTERNET" />
再次见到熟悉的WeatherInfoService
public interface WeatherInfoService {
    @GET("http://v.juhe.cn/weather/index?format=2&cityname=北京&key=b952ad7acbc7415f3f3c9bf274e39c45")
    Observable<WeatherInfo> getWeatherInfoByRxJava();
}注意这里getWeatherInfoByRxJava() 的返回类型为Observable<WeatherInfo>, 这也就意味着我们在这里直接得到一个被观察者Observable!
还是那个MainActivity
        findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Gson gson = new GsonBuilder().create();
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        //配置转化库,默认是Gson
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        //配置回调库,採用RxJava
                        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .build();
                WeatherInfoService weatherInfoService = retrofit.create(WeatherInfoService.class);
                getWeatherInfo(weatherInfoService,gson);
                getWeatherInfoByMap(weatherInfoService,gson);
                getWeatherInfoByFlatMap(weatherInfoService,gson);
             }
        });注意.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) ,这行代码的作用是配置Retrofit回调库,採用RxJava。 
这里我们写了getWeatherInfo(weatherInfoService,gson);、getWeatherInfoByMap(weatherInfoService,gson); 和getWeatherInfoByFlatMap(weatherInfoService,gson);三个方法。接下来会一一解说
MainActivity#getWeatherInfo()
在这种方法里实现了最主要的RxJava/RxAndroid和Retrofit的结合。代码例如以下
        weatherInfoService.getWeatherInfoByRxJava()// 返回类型为Observable<WeatherInfo>
                .subscribeOn(Schedulers.io())// 指定订阅者在io线程(第一次指定订阅者线程有效)
                .doOnSubscribe(new Action0() { //doOnSubscribe线程为近期的subscribeOn指定线程
                    @Override
                    public void call() {
                        Toast.makeText(MainActivity.this, "我在网络请求前运行", Toast.LENGTH_SHORT).show();
                    }
                })
                .subscribeOn(AndroidSchedulers.mainThread())// 指定在主线程
                .observeOn(AndroidSchedulers.mainThread())// 指定观察者在主线程
                .subscribe(new Subscriber<WeatherInfo>() {
                    @Override
                    public void onCompleted() {
                        Log.i(TAG, "onCompleted");
                    }
                    @Override
                    public void onError(Throwable e) {
                        tv.setText("error:" + e.getMessage());
                    }
                    @Override
                    public void onNext(WeatherInfo weatherInfo) {
                        Log.i(TAG, gson.toJson(weatherInfo));
                        tv.setText(gson.toJson(weatherInfo));
                    }
                });代码里凝视非常多。补充几个须要注意的地方。 
1. subscribeOn()仅仅有第一次调用的时候就指定被观察者Observable所在线程。以后能够多次调用。但被观察者Observable所在线程已经指定 
2. doOnSubscribe()在发送事件前运行,能够指定运行线程。
一般在里面展示loading 
3. observeOn()可多次调用而且每次都会改变观察者Observer/Subscriber所在线程。
MainActivity#getWeatherInfoByMap()
Observable的map()是个奇妙的方法。它能够对被观察者Observable的泛型进行操作,而且返回还有一个Observable传递给观察者Observer/Subscriber
    private void getWeatherInfoByMap(WeatherInfoService weatherInfoService, final Gson gson) {
        weatherInfoService.getWeatherInfoByRxJava()// 返回类型为Observable<WeatherInfo>
                .subscribeOn(Schedulers.io())// 指定订阅者在io线程(第一次指定订阅者线程有效)
                .doOnSubscribe(new Action0() { //doOnSubscribe线程为近期的subscribeOn指定线程
                    @Override
                    public void call() {
                        Toast.makeText(MainActivity.this, "我在网络请求前运行", Toast.LENGTH_SHORT).show();
                    }
                })
                .subscribeOn(AndroidSchedulers.mainThread())// 指定在主线程
                .map(new Func1<WeatherInfo, Today>() {
                    @Override
                    public Today call(WeatherInfo weatherInfo) {
                        return weatherInfo.getResult().getToday();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())// 指定观察者在主线程
                .subscribe(new Subscriber<Today>() {
                    ...
                    @Override
                    public void onNext(Today today) {
                        tv.setText(gson.toJson(today));
                    }
                });
    }在.map()方法中我们获取WeatherInfo中Today属性,而且返回Today。然后再观察者Subscriber我们就能够直接对Today进行操作。是不是非常方便?还有更方便的!
MainActivity#getWeatherInfoByFlatMap()
使用.map方法仅仅能返回一个值,属于一对一类型。
RxJava给我们提供一个更奇妙的方法.flatMap()。
    private void getWeatherInfoByFlatMap(WeatherInfoService weatherInfoService, final Gson gson) {
        weatherInfoService.getWeatherInfoByRxJava()
                .subscribeOn(Schedulers.io())
                .flatMap(new Func1<WeatherInfo, Observable<Future>>(){
                    @Override
                    public Observable<Future> call(WeatherInfo weatherInfo) {
                        return Observable.from(weatherInfo.getResult().getFuture());
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Future>() {
                    @Override
                    public void onCompleted() {
                        tv.setText(sb);
                    }
                    @Override
                    public void onError(Throwable e) {
                    }
                    @Override
                    public void onNext(Future future) {
                        Log.i(TAG,gson.toJson(future));
                       sb.append(gson.toJson(future)+"\n");
                    }
                });
    }这种方法有些难以理解,以下具体介绍关键部分代码。首先在.flatMap()中 第一个參数为被观察者Observable的泛型WeatherInfo。第二个參数定义为还有一个被观察者,为了叙述方便,下文称第一个被观察者A。第二个參数即还有一个被观察者称为B。A的泛型为WeatherInfo。B的泛型为Future。getFuture是这么被定义的
public class WeatherInfo {
    private String resultcode;
    private String reason;
    private String error_code;
    private Result result;
    ...
}
public class Result {
    private SK sk;
    private Today today;
    private List<Future> future;
    public List<Future> getFuture() {
        return future;
    }
    ...
}原来getFuture()返回的是个List<Future>,但是在Func1的call() 返回值怎么怎么是Observable<Future>?这是由于Observable.from()会将List<Future> 拆分成一个个的Future返回,也就是说订阅者的onNext 方法将会被运行List<Future>.seze() 次。所以这里我们定义了一个sb(StringBuilder)。用于将每次返回的Future拼接起来,最后在onCompleted() 中调用tv.setText(sb);
结束语
至此,RxJava/RxAndroid结合Retrofit解说完成,希望能对读者有所帮助。感谢耐心读到最后!
源代码下载地址:0分仅仅为共享
參考: 
http://gank.io/post/560e15be2dca930e00da1083 
http://blog.csdn.net/liuhongwei123888/article/details/50375897
Android RxJava/RxAndroid结合Retrofit使用的更多相关文章
- 【Android - 框架】之Retrofit+RxJava的使用
		前几天分别对Retrofit和RxJava进行了总结,这个帖子打算把Retrofit结合RxJava使用的方法总结以下.有还不了解Retrofit或RxJava的朋友可以参考下面的帖子学习~ [And ... 
- Android 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器aaa
		MDPlayer万能播放器 MDPlayer,基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器,可以播 ... 
- RxJava Rxandroid retrofit
		其实Retrofit会了.集合RxJava,RxAndroid 就很简单了. 只需要改几个地方. 1.接口里面返回的对象不再是 call,而是Observable public interface A ... 
- RxAndroid结合Retrofit,看看谁才是最佳拍档!
		这篇博文酝酿好久了,今天终于下定决心开始写!RxAndroid和Retrofit都算是当下非常流行的Android开发框架,这两个框架光是单独使用就已经爽歪歪了,那么将RxAndroid和Retrof ... 
- RxJava RxAndroid【简介】
		资源 RxJava:https://github.com/ReactiveX/RxJava RxAndroid :https://github.com/ReactiveX/RxAndroid 官网:h ... 
- Android RxJava 2 的用法 just 、from、map、subscribe、flatmap、Flowable、Function、Consumer ...【转】
		先简单说说RxJava的用途与价值 原文出处:Android RxJava 2 的用法 用途: 异步 (也就是开线程跳转) 价值: 面对复杂的逻辑,它依然 简洁 ,代码 易读 RxJava2 与 Rx ... 
- 【Android实战】----从Retrofit源代码分析到Java网络编程以及HTTP权威指南想到的
		一.简单介绍 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明确为什么Retrofit那么屌. 近期也看了一些其源代码分析的文章以及亲自查看了源代码 ... 
- [置顶]
        【Android实战】----从Retrofit源码分析到Java网络编程以及HTTP权威指南想到的
		一.简介 接上一篇[Android实战]----基于Retrofit实现多图片/文件.图文上传中曾说非常想搞明白为什么Retrofit那么屌.最近也看了一些其源码分析的文章以及亲自查看了源码,发现其对 ... 
- Rxjava, RxAndroid, Retrofit 等库的使用
		RxJava的基本用法: 关于 unSubscribe() 的调用问题: There is no need to unsubscribe in onCompleted. Take a look at ... 
随机推荐
- react native native module
			React Native Native Modules,官方地址:https://facebook.github.io/react-native/docs/native-modules-android ... 
- POJ2828 Buy Tickets [树状数组,二分答案]
			题目传送门 Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 22611 Accepted: 110 ... 
- 洛谷P1007 独木桥 [数论]
			题目传送门 独木桥 题目背景 战争已经进入到紧要时间.你是运输小队长,正在率领运输部队向前线运送物资.运输任务像做题一样的无聊.你希望找些刺激,于是命令你的士兵们到前方的一座独木桥上欣赏风景,而你留在 ... 
- StreamingAssets文件夹的读取异常
			1.今天在读取StreamingAssets文件夹中的文本文件的时候,出现了异常,花了一个多小时解决了,把解决结果给大家梳理一下 2.文本文件夹所在位置:在StreamingAssets文件夹中新建一 ... 
- WAR/EAR 概念
			In J2EE application, modules are packaged as EAR, JAR and WAR based on their functionality JAR: EJB ... 
- 发现一个FreeSWITCH bug
			在研究FreeSWITCH视频会议的混屏问题时候发现一个bug. 已提交jira. 附上代码,问题很明显,不解释 =========================================== ... 
- Android异步消息处理机制(多线程)
			当我们需要执行一些耗时操作,比如说发起一条网络请求时,考虑到网速等其他原因,服务器未必会立刻响应我们的请求,如果不将这类操作放在子线程里去执行,就会导致主线程被阻塞住,从而影响用户对软件的正常使用. ... 
- 自定义word快捷键,设置插入图片快捷键
			韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 自定义word快捷键,设置插入图片快捷键 文件→选项→自定义功能区 选择键盘快捷方式 自 ... 
- Java中的对象池技术
			java中的对象池技术,是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个出来(如果池中没有则创建一个),则在需要重复重复创建相等变量时节省了很多时间.对象池其实也就是一个内存 ... 
- [Codeforces #174] Tutorial
			Link: Codeforces #174 传送门 A: 求原根的个数,有一条性质是原根个数为$\phi(\phi(n))$,多了一个不会证的性质 如果要确定哪些是原根的话还是要枚举,不过对于每个数不 ... 
