原文地址:http://blog.csdn.net/maplejaw_/article/details/52442065

Observable

在RxJava1.x中,最熟悉的莫过于Observable这个类了,笔者刚使用RxJava2.x时,创建一个Observable后,顿时是懵逼的。因为我们熟悉的Subscriber居然没影了,取而代之的是ObservableEmitter,俗称发射器。此外,由于没有了Subscriber的踪影,我们创建观察者时需使用Observer。而Observer也不是我们熟悉的那个Observer,其回调的Disposable参数更是让人摸不到头脑。

废话不多说,从会用开始,还记得使用RxJava的三部曲吗? 
第一步:初始化一个Observable

  1. Observable<Integer> observable=Observable.create(new ObservableOnSubscribe<Integer>() {
  2. @Override
  3. public void subscribe(ObservableEmitter<Integer> e) throws Exception {
  4. e.onNext(1);
  5. e.onNext(2);
  6. e.onComplete();
  7. }
  8. });

第二步:初始化一个Observer

  1. Observer<Integer> observer= new Observer<Integer>() {
  2. @Override
  3. public void onSubscribe(Disposable d) {
  4. }
  5. @Override
  6. public void onNext(Integer value) {
  7. }
  8. @Override
  9. public void onError(Throwable e) {
  10. }
  11. @Override
  12. public void onComplete() {
  13. }
  14. }

第三部:建立订阅关系

  1. 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中则非常简便,如下操作即可。

  1. Observer<Integer> observer = new Observer<Integer>() {
  2. private Disposable disposable;
  3. @Override
  4. public void onSubscribe(Disposable d) {
  5. disposable = d;
  6. }
  7. @Override
  8. public void onNext(Integer value) {
  9. Log.d("JG", value.toString());
  10. if (value > 3) {   // >3 时为异常数据,解除订阅
  11. disposable.dispose();
  12. }
  13. }
  14. @Override
  15. public void onError(Throwable e) {
  16. }
  17. @Override
  18. public void onComplete() {
  19. }
  20. };

此外,RxJava2.x中仍然保留了其他简化订阅方法,我们可以根据需求,选择相应的简化订阅。只不过传入的对象改为了Consumer。`

  1. Disposable disposable = observable.subscribe(new Consumer<Integer>() {
  2. @Override
  3. public void accept(Integer integer) throws Exception {
  4. //这里接收数据项
  5. }
  6. }, new Consumer<Throwable>() {
  7. @Override
  8. public void accept(Throwable throwable) throws Exception {
  9. //这里接收onError
  10. }
  11. }, new Action() {
  12. @Override
  13. public void run() throws Exception {
  14. //这里接收onComplete。
  15. }
  16. });

不同于RxJava1.x,RxJava2.x中没有了一系列的Action/Func接口,取而代之的是与Java8命名类似的函数式接口,如下图:

其中Action类似于RxJava1.x中的Action0,区别在于Action允许抛出异常。

  1. public interface Action {
  2. /**
  3. * Runs the action and optionally throws a checked exception
  4. * @throws Exception if the implementation wishes to throw a checked exception
  5. */
  6. void run() throws Exception;
  7. }

而Consumer即消费者,用于接收单个值,BiConsumer则是接收两个值,Function用于变换对象,Predicate用于判断。这些接口命名大多参照了Java8,熟悉Java8新特性的应该都知道意思,这里也就不再赘述了。

线程调度

关于线程切换这点,RxJava1.x和RxJava2.x的实现思路是一样的。这里就简单看下相关源码。

subscribeOn

同RxJava1.x一样,subscribeOn用于指定subscribe()时所发生的线程,从源码角度可以看出,内部线程调度是通过ObservableSubscribeOn来实现的。

  1. public final Observable<T> subscribeOn(Scheduler scheduler) {
  2. ObjectHelper.requireNonNull(scheduler, "scheduler is null");
  3. return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
  4. }

ObservableSubscribeOn的核心源码在subscribeActual方法中,通过代理的方式使用SubscribeOnObserver包装Observer后,设置Disposable来将subscribe切换到Scheduler线程中

  1. @Override
  2. public void subscribeActual(final Observer<? super T> s) {
  3. final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
  4. s.onSubscribe(parent); //回调Disposable
  5. parent.setDisposable(scheduler.scheduleDirect(new Runnable() { //设置`Disposable`
  6. @Override
  7. public void run() {
  8. source.subscribe(parent); //使Observable的subscribe发生在Scheduler线程中
  9. }
  10. }));
  11. }

observeOn

observeOn方法用于指定下游Observer回调发生的线程。

  1. public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
  2. //..
  3. //验证安全
  4. return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
  5. }

主要实现在ObservableObserveOn中的subscribeActual,可以看出,不同于subscribeOn,没有将suncribe操作全部切换到Scheduler中,而是通过ObserveOnSubscriber与Scheduler配合,通过schedule()达到切换下游Observer回调发生的线程,这一点与RxJava1.x实现几乎相同。关于ObserveOnSubscriber的源码这里不再重复描述了,有兴趣的可以查看本人RxJava源码解读这篇文章

  1. @Override
  2. protected void subscribeActual(Observer<? super T> observer) {
  3. if (scheduler instanceof TrampolineScheduler) {
  4. source.subscribe(observer);
  5. } else {
  6. Scheduler.Worker w = scheduler.createWorker();
  7. source.subscribe(new ObserveOnSubscriber<T>(observer, w, delayError, bufferSize));
  8. }
  9. }

Flowable

Flowable是RxJava2.x中新增的类,专门用于应对背压(Backpressure)问题,但这并不是RxJava2.x中新引入的概念。所谓背压,即生产者的速度大于消费者的速度带来的问题,比如在Android中常见的点击事件,点击过快则会造成点击两次的效果。 
我们知道,在RxJava1.x中背压控制是由Observable完成的,使用如下:

  1. Observable.range(1,10000)
  2. .onBackpressureDrop()
  3. .subscribe(integer -> Log.d("JG",integer.toString()));

而在RxJava2.x中将其独立了出来,取名为Flowable。因此,原先的Observable已经不具备背压处理能力。 
通过Flowable我们可以自定义背压处理策略。

测试Flowable例子如下:

  1. Flowable.create(new FlowableOnSubscribe<Integer>() {
  2. @Override
  3. public void subscribe(FlowableEmitter<Integer> e) throws Exception {
  4. for(int i=0;i<10000;i++){
  5. e.onNext(i);
  6. }
  7. e.onComplete();
  8. }
  9. }, FlowableEmitter.BackpressureMode.ERROR) //指定背压处理策略,抛出异常
  10. .subscribeOn(Schedulers.computation())
  11. .observeOn(Schedulers.newThread())
  12. .subscribe(new Consumer<Integer>() {
  13. @Override
  14. public void accept(Integer integer) throws Exception {
  15. Log.d("JG", integer.toString());
  16. Thread.sleep(1000);
  17. }
  18. }, new Consumer<Throwable>() {
  19. @Override
  20. public void accept(Throwable throwable) throws Exception {
  21. Log.d("JG",throwable.toString());
  22. }
  23. });

或者可以使用类似RxJava1.x的方式来控制。

  1. Flowable.range(1,10000)
  2. .onBackpressureDrop()
  3. .subscribe(integer -> Log.d("JG",integer.toString()));

其中还需要注意的一点在于,Flowable并不是订阅就开始发送数据,而是需等到执行Subscription#request才能开始发送数据。当然,使用简化subscribe订阅方法会默认指定Long.MAX_VALUE。手动指定的例子如下:

  1. Flowable.range(1,10).subscribe(new Subscriber<Integer>() {
  2. @Override
  3. public void onSubscribe(Subscription s) {
  4. s.request(Long.MAX_VALUE);//设置请求数
  5. }
  6. @Override
  7. public void onNext(Integer integer) {
  8. }
  9. @Override
  10. public void onError(Throwable t) {
  11. }
  12. @Override
  13. public void onComplete() {
  14. }
  15. });

Single

不同于RxJava1.x中的SingleSubscriber,RxJava2中的SingleObserver多了一个回调方法onSubscribe。

  1. interface SingleObserver<T> {
  2. void onSubscribe(Disposable d);
  3. void onSuccess(T value);
  4. void onError(Throwable error);
  5. }

Completable

同Single,Completable也被重新设计为Reactive-Streams架构,RxJava1.x的CompletableSubscriber改为CompletableObserver,源码如下:

  1. interface CompletableObserver<T> {
  2. void onSubscribe(Disposable d);
  3. void onComplete();
  4. void onError(Throwable error);
  5. }

Subject/Processor

Processor和Subject的作用是相同的。关于Subject部分,RxJava1.x与RxJava2.x在用法上没有显著区别,这里就不介绍了。其中Processor是RxJava2.x新增的,继承自Flowable,所以支持背压控制。而Subject则不支持背压控制。使用如下:

  1. //Subject
  2. AsyncSubject<String> subject = AsyncSubject.create();
  3. subject.subscribe(o -> Log.d("JG",o));//three
  4. subject.onNext("one");
  5. subject.onNext("two");
  6. subject.onNext("three");
  7. subject.onComplete();
  8. //Processor
  9. AsyncProcessor<String> processor = AsyncProcessor.create();
  10. processor.subscribe(o -> Log.d("JG",o)); //three
  11. processor.onNext("one");
  12. processor.onNext("two");
  13. processor.onNext("three");
  14. 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 浅析的更多相关文章

  1. [Android] Android RxJava2+Retrofit2+OkHttp3 的使用(一) --基础篇 Retrofit2 的使用

    本文是 Android RxJava2+Retrofit2+OkHttp3 的使用(一) --基础篇 Retrofit2 的使用 本文的目标是用 Retrofit写一个网络请求: 本文以从获取天气预报 ...

  2. [Android] Android RxJava2+Retrofit2+OkHttp3 的使用

    [Android] Android RxJava2+Retrofit2+OkHttp3 简单介绍Retrofit.OKHttp和RxJava之间的关系: Retrofit:Retrofit是Squar ...

  3. Android AIDL浅析及异步使用

    AIDL:Android Interface Definition Language,即 Android 接口定义语言. AIDL 是什么 Android 系统中的进程之间不能共享内存,因此,需要提供 ...

  4. android framework浅析_转

    Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...

  5. Android框架浅析之锁屏(Keyguard)机制原理

    最近终于成功的摆脱了FM收音机,迈向了新的模块:锁屏.状态栏.Launcher---姑且称之为“IDLE”小组,或许叫手机 美容小组,要是能施展下周星星同学的还我漂漂拳,岂不快哉. OK,闲话打住,咱 ...

  6. Android framework浅析[转]

    Android系统从底向上一共分了4层,每一层都把底层实现封装,并暴露调用接口给上一层. 1. Linux内核(Linux Kernel) 1)Android运行在linux kernel 2.6之上 ...

  7. Android项目--浅析系统通讯录中的那些方法

    系统通讯录,以前的版本虽然过时了,不过有些东西还是可以用. 1.开启系统联系人添加 /** 添加联系人 */ Intent intent = new Intent(Intent.ACTION_INSE ...

  8. Macaca之Android原理浅析

    经过研究macaca的android模块源码,原理主要由以下三块构成 一.uiautomator TODO 二.nanohttp TODO 二.adb forward TODO

  9. Android DecorView浅析

    摘要 一.DecorView为整个Window界面的最顶层View. 二.DecorView只有一个子元素为LinearLayout.代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域. ...

随机推荐

  1. pkill有的时候并不能杀死进程?

    pkill的用法:http://man.linuxde.net/pkill 根据进程命令行,杀死进程 如下intellij.go代码为一个代理服务器,把本地请求转向一个代理 package main ...

  2. python加载和使用java的类的方法

    在开发python项目的时候,有时候会用的java的jar包 有这么几个python的三方包可以用: pyjnius:bug list:https://github.com/kivy/pyjnius/ ...

  3. Android: Mac无法找到Android SDK问题

    通过brew cask install android-sdk后,Intellij Idea中设置Android SDK路径失败,解决方法如下: /usr/local/Caskroom/android ...

  4. 配置文件的备份和IOS 的备份

    分享到 QQ空间 新浪微博 百度搜藏 人人网 腾讯微博 开心网 腾讯朋友 百度空间 豆瓣网 搜狐微博 百度新首页 QQ收藏 和讯微博 我的淘宝 百度贴吧 更多... 百度分享 广场 登录 注册 关注此 ...

  5. 制作svg动画

    要实现一步一步画出来一个图片,css3做不到吧.除非一张张的图片定时显示.想不到别的招了.如今用的是一个插件,做了一个svg动画. 插件地址:http://lazylinepainter.info/ ...

  6. node安装-Win+Linux+Mac osx

    node下载地址,除了Mac osx或Win平台,仅有Linux平台命令安装. Win.Mac 点击即可下载(注:Mac有dmg和pkg安装格式). Linux分为Redhot和Deepin系列,安装 ...

  7. 【动态规划】Dynamic Programming

    动态规划 一.动态规划 动态规划(Dynamic Programming)是一种设计的技巧,是解决多阶段决策过程最优化问题的通用方法. 基本思想:将待求解问题分解成若干个子问题,先求解子问题,然后从这 ...

  8. Mariadb 索引及外键

    索引 索引相当于一本书的目录,在一个数据库或表有索引的情况下,会很便于查询数据,使查询更加效率,相对的也有缺点,不利于去修改,比较麻烦,有索引便于查询,那就意味着索引创建的越多越好么?然而并不是:索引 ...

  9. [办公自动化]如何将PPT转为PDF,免费

    同事需要把PPT格式的文档转为PDF.她没有安装adobe acrobat,安装了微软office 2007. 这个其实可以通过安装微软官方插件来解决.无需额外费用. 所需软件为: 2007 Micr ...

  10. 【OI】Kruskal & ufs (克鲁斯卡与并查集)

    Kruskal是有关于最小生成树的算法. 这个算法非常好理解,用一句话来概括就是: 从小到大找不同集合的边. 那么,具体是怎样的呢. 1.先把所有顶点初始化为一个连通分量. 2.从所有边中选择最小的( ...