Android RxJava2 浅析
原文地址:http://blog.csdn.net/maplejaw_/article/details/52442065
Observable
在RxJava1.x中,最熟悉的莫过于Observable这个类了,笔者刚使用RxJava2.x时,创建一个Observable后,顿时是懵逼的。因为我们熟悉的Subscriber居然没影了,取而代之的是ObservableEmitter,俗称发射器。此外,由于没有了Subscriber的踪影,我们创建观察者时需使用Observer。而Observer也不是我们熟悉的那个Observer,其回调的Disposable参数更是让人摸不到头脑。
废话不多说,从会用开始,还记得使用RxJava的三部曲吗?
第一步:初始化一个Observable
- Observable<Integer> observable=Observable.create(new ObservableOnSubscribe<Integer>() {
- @Override
- public void subscribe(ObservableEmitter<Integer> e) throws Exception {
- e.onNext(1);
- e.onNext(2);
- e.onComplete();
- }
- });
第二步:初始化一个Observer
- Observer<Integer> observer= new Observer<Integer>() {
- @Override
- public void onSubscribe(Disposable d) {
- }
- @Override
- public void onNext(Integer value) {
- }
- @Override
- public void onError(Throwable e) {
- }
- @Override
- public void onComplete() {
- }
- }
第三部:建立订阅关系
- observable.subscribe(observer); //建立订阅关系
不难看出,与RxJava1.x还是存在着一些区别的。首先,创建Observable时,回调的是ObservableEmitter,字面意思即发射器,用于发射数据(onNext)和通知(onError/onComplete)。其次,创建的Observer中多了一个回调方法onSubscribe,传递参数为Disposable ,Disposable相当于RxJava1.x中的Subscription,用于解除订阅。你可能纳闷为什么不像RxJava1.x中订阅时返回Disposable,而是选择回调出来呢。官方说是为了设计成Reactive-Streams架构。不过仔细想想这么一个场景还是很有用的,假设Observer需要在接收到异常数据项时解除订阅,在RxJava2.x中则非常简便,如下操作即可。
- Observer<Integer> observer = new Observer<Integer>() {
- private Disposable disposable;
- @Override
- public void onSubscribe(Disposable d) {
- disposable = d;
- }
- @Override
- public void onNext(Integer value) {
- Log.d("JG", value.toString());
- if (value > 3) { // >3 时为异常数据,解除订阅
- disposable.dispose();
- }
- }
- @Override
- public void onError(Throwable e) {
- }
- @Override
- public void onComplete() {
- }
- };
此外,RxJava2.x中仍然保留了其他简化订阅方法,我们可以根据需求,选择相应的简化订阅。只不过传入的对象改为了Consumer。`
- Disposable disposable = observable.subscribe(new Consumer<Integer>() {
- @Override
- public void accept(Integer integer) throws Exception {
- //这里接收数据项
- }
- }, new Consumer<Throwable>() {
- @Override
- public void accept(Throwable throwable) throws Exception {
- //这里接收onError
- }
- }, new Action() {
- @Override
- public void run() throws Exception {
- //这里接收onComplete。
- }
- });
不同于RxJava1.x,RxJava2.x中没有了一系列的Action/Func接口,取而代之的是与Java8命名类似的函数式接口,如下图:

其中Action类似于RxJava1.x中的Action0,区别在于Action允许抛出异常。
- public interface Action {
- /**
- * Runs the action and optionally throws a checked exception
- * @throws Exception if the implementation wishes to throw a checked exception
- */
- void run() throws Exception;
- }
而Consumer即消费者,用于接收单个值,BiConsumer则是接收两个值,Function用于变换对象,Predicate用于判断。这些接口命名大多参照了Java8,熟悉Java8新特性的应该都知道意思,这里也就不再赘述了。
线程调度
关于线程切换这点,RxJava1.x和RxJava2.x的实现思路是一样的。这里就简单看下相关源码。
subscribeOn
同RxJava1.x一样,subscribeOn用于指定subscribe()时所发生的线程,从源码角度可以看出,内部线程调度是通过ObservableSubscribeOn来实现的。
- public final Observable<T> subscribeOn(Scheduler scheduler) {
- ObjectHelper.requireNonNull(scheduler, "scheduler is null");
- return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
- }
ObservableSubscribeOn的核心源码在subscribeActual方法中,通过代理的方式使用SubscribeOnObserver包装Observer后,设置Disposable来将subscribe切换到Scheduler线程中
- @Override
- public void subscribeActual(final Observer<? super T> s) {
- final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
- s.onSubscribe(parent); //回调Disposable
- parent.setDisposable(scheduler.scheduleDirect(new Runnable() { //设置`Disposable`
- @Override
- public void run() {
- source.subscribe(parent); //使Observable的subscribe发生在Scheduler线程中
- }
- }));
- }
observeOn
observeOn方法用于指定下游Observer回调发生的线程。
- public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
- //..
- //验证安全
- return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
- }
主要实现在ObservableObserveOn中的subscribeActual,可以看出,不同于subscribeOn,没有将suncribe操作全部切换到Scheduler中,而是通过ObserveOnSubscriber与Scheduler配合,通过schedule()达到切换下游Observer回调发生的线程,这一点与RxJava1.x实现几乎相同。关于ObserveOnSubscriber的源码这里不再重复描述了,有兴趣的可以查看本人RxJava源码解读这篇文章
- @Override
- protected void subscribeActual(Observer<? super T> observer) {
- if (scheduler instanceof TrampolineScheduler) {
- source.subscribe(observer);
- } else {
- Scheduler.Worker w = scheduler.createWorker();
- source.subscribe(new ObserveOnSubscriber<T>(observer, w, delayError, bufferSize));
- }
- }
Flowable
Flowable是RxJava2.x中新增的类,专门用于应对背压(Backpressure)问题,但这并不是RxJava2.x中新引入的概念。所谓背压,即生产者的速度大于消费者的速度带来的问题,比如在Android中常见的点击事件,点击过快则会造成点击两次的效果。
我们知道,在RxJava1.x中背压控制是由Observable完成的,使用如下:
- Observable.range(1,10000)
- .onBackpressureDrop()
- .subscribe(integer -> Log.d("JG",integer.toString()));
而在RxJava2.x中将其独立了出来,取名为Flowable。因此,原先的Observable已经不具备背压处理能力。
通过Flowable我们可以自定义背压处理策略。

测试Flowable例子如下:
- Flowable.create(new FlowableOnSubscribe<Integer>() {
- @Override
- public void subscribe(FlowableEmitter<Integer> e) throws Exception {
- for(int i=0;i<10000;i++){
- e.onNext(i);
- }
- e.onComplete();
- }
- }, FlowableEmitter.BackpressureMode.ERROR) //指定背压处理策略,抛出异常
- .subscribeOn(Schedulers.computation())
- .observeOn(Schedulers.newThread())
- .subscribe(new Consumer<Integer>() {
- @Override
- public void accept(Integer integer) throws Exception {
- Log.d("JG", integer.toString());
- Thread.sleep(1000);
- }
- }, new Consumer<Throwable>() {
- @Override
- public void accept(Throwable throwable) throws Exception {
- Log.d("JG",throwable.toString());
- }
- });
或者可以使用类似RxJava1.x的方式来控制。
- Flowable.range(1,10000)
- .onBackpressureDrop()
- .subscribe(integer -> Log.d("JG",integer.toString()));
其中还需要注意的一点在于,Flowable并不是订阅就开始发送数据,而是需等到执行Subscription#request才能开始发送数据。当然,使用简化subscribe订阅方法会默认指定Long.MAX_VALUE。手动指定的例子如下:
- Flowable.range(1,10).subscribe(new Subscriber<Integer>() {
- @Override
- public void onSubscribe(Subscription s) {
- s.request(Long.MAX_VALUE);//设置请求数
- }
- @Override
- public void onNext(Integer integer) {
- }
- @Override
- public void onError(Throwable t) {
- }
- @Override
- public void onComplete() {
- }
- });
Single
不同于RxJava1.x中的SingleSubscriber,RxJava2中的SingleObserver多了一个回调方法onSubscribe。
- interface SingleObserver<T> {
- void onSubscribe(Disposable d);
- void onSuccess(T value);
- void onError(Throwable error);
- }
Completable
同Single,Completable也被重新设计为Reactive-Streams架构,RxJava1.x的CompletableSubscriber改为CompletableObserver,源码如下:
- interface CompletableObserver<T> {
- void onSubscribe(Disposable d);
- void onComplete();
- void onError(Throwable error);
- }
Subject/Processor
Processor和Subject的作用是相同的。关于Subject部分,RxJava1.x与RxJava2.x在用法上没有显著区别,这里就不介绍了。其中Processor是RxJava2.x新增的,继承自Flowable,所以支持背压控制。而Subject则不支持背压控制。使用如下:
- //Subject
- AsyncSubject<String> subject = AsyncSubject.create();
- subject.subscribe(o -> Log.d("JG",o));//three
- subject.onNext("one");
- subject.onNext("two");
- subject.onNext("three");
- subject.onComplete();
- //Processor
- AsyncProcessor<String> processor = AsyncProcessor.create();
- processor.subscribe(o -> Log.d("JG",o)); //three
- processor.onNext("one");
- processor.onNext("two");
- processor.onNext("three");
- processor.onComplete();
操作符
关于操作符,RxJava1.x与RxJava2.x在命名和行为上大多数保持了一致,部分操作符请查阅文档。
最后
RxJava1.x 如何平滑升级到RxJava2.x?
由于RxJava2.x变化较大无法直接升级,幸运的是,官方提供了RxJava2Interop这个库,可以方便地将RxJava1.x升级到RxJava2.x,或者将RxJava2.x转回RxJava1.x。地址:https://github.com/akarnokd/RxJava2Interop
Android RxJava2 浅析的更多相关文章
- [Android] Android RxJava2+Retrofit2+OkHttp3 的使用(一) --基础篇 Retrofit2 的使用
本文是 Android RxJava2+Retrofit2+OkHttp3 的使用(一) --基础篇 Retrofit2 的使用 本文的目标是用 Retrofit写一个网络请求: 本文以从获取天气预报 ...
- [Android] Android RxJava2+Retrofit2+OkHttp3 的使用
[Android] Android RxJava2+Retrofit2+OkHttp3 简单介绍Retrofit.OKHttp和RxJava之间的关系: Retrofit:Retrofit是Squar ...
- Android AIDL浅析及异步使用
AIDL:Android Interface Definition Language,即 Android 接口定义语言. AIDL 是什么 Android 系统中的进程之间不能共享内存,因此,需要提供 ...
- android framework浅析_转
Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...
- Android框架浅析之锁屏(Keyguard)机制原理
最近终于成功的摆脱了FM收音机,迈向了新的模块:锁屏.状态栏.Launcher---姑且称之为“IDLE”小组,或许叫手机 美容小组,要是能施展下周星星同学的还我漂漂拳,岂不快哉. OK,闲话打住,咱 ...
- Android framework浅析[转]
Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...
- Android项目--浅析系统通讯录中的那些方法
系统通讯录,以前的版本虽然过时了,不过有些东西还是可以用. 1.开启系统联系人添加 /** 添加联系人 */ Intent intent = new Intent(Intent.ACTION_INSE ...
- Macaca之Android原理浅析
经过研究macaca的android模块源码,原理主要由以下三块构成 一.uiautomator TODO 二.nanohttp TODO 二.adb forward TODO
- Android DecorView浅析
摘要 一.DecorView为整个Window界面的最顶层View. 二.DecorView只有一个子元素为LinearLayout.代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域. ...
随机推荐
- pkill有的时候并不能杀死进程?
pkill的用法:http://man.linuxde.net/pkill 根据进程命令行,杀死进程 如下intellij.go代码为一个代理服务器,把本地请求转向一个代理 package main ...
- python加载和使用java的类的方法
在开发python项目的时候,有时候会用的java的jar包 有这么几个python的三方包可以用: pyjnius:bug list:https://github.com/kivy/pyjnius/ ...
- Android: Mac无法找到Android SDK问题
通过brew cask install android-sdk后,Intellij Idea中设置Android SDK路径失败,解决方法如下: /usr/local/Caskroom/android ...
- 配置文件的备份和IOS 的备份
分享到 QQ空间 新浪微博 百度搜藏 人人网 腾讯微博 开心网 腾讯朋友 百度空间 豆瓣网 搜狐微博 百度新首页 QQ收藏 和讯微博 我的淘宝 百度贴吧 更多... 百度分享 广场 登录 注册 关注此 ...
- 制作svg动画
要实现一步一步画出来一个图片,css3做不到吧.除非一张张的图片定时显示.想不到别的招了.如今用的是一个插件,做了一个svg动画. 插件地址:http://lazylinepainter.info/ ...
- node安装-Win+Linux+Mac osx
node下载地址,除了Mac osx或Win平台,仅有Linux平台命令安装. Win.Mac 点击即可下载(注:Mac有dmg和pkg安装格式). Linux分为Redhot和Deepin系列,安装 ...
- 【动态规划】Dynamic Programming
动态规划 一.动态规划 动态规划(Dynamic Programming)是一种设计的技巧,是解决多阶段决策过程最优化问题的通用方法. 基本思想:将待求解问题分解成若干个子问题,先求解子问题,然后从这 ...
- Mariadb 索引及外键
索引 索引相当于一本书的目录,在一个数据库或表有索引的情况下,会很便于查询数据,使查询更加效率,相对的也有缺点,不利于去修改,比较麻烦,有索引便于查询,那就意味着索引创建的越多越好么?然而并不是:索引 ...
- [办公自动化]如何将PPT转为PDF,免费
同事需要把PPT格式的文档转为PDF.她没有安装adobe acrobat,安装了微软office 2007. 这个其实可以通过安装微软官方插件来解决.无需额外费用. 所需软件为: 2007 Micr ...
- 【OI】Kruskal & ufs (克鲁斯卡与并查集)
Kruskal是有关于最小生成树的算法. 这个算法非常好理解,用一句话来概括就是: 从小到大找不同集合的边. 那么,具体是怎样的呢. 1.先把所有顶点初始化为一个连通分量. 2.从所有边中选择最小的( ...