RxJava 1升级到RxJava 2过程中踩过的一些“坑”

RxJava2介绍

RxJava2 发布已经有一段时间了,是对 RxJava 的一次重大的升级,由于我的一个库cv4j使用了 RxJava2 来尝鲜,但是 RxJava2 跟 RxJava1 是不能同时存在于一个项目中的,逼不得已我得把自己所有框架中使用 RxJava 的地方以及
App 中使用 RxJava 的地方都升级到最新版本。所以我整理并记录了一些已经填好的坑。分享出来供大家参考学习,下面来看看详细的介绍:

填坑记录

1. RxJava1 跟 RxJava2 不能共存

如果,在同一个module中同时使用RxJava1和RxJava2,类似如下:

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'

那么,很不幸你会遇到这样的错误

同理,在 App 中如果使用了 Rxjava2,但是某个第三方的 library 还在使用 Rxjava1 也会遇到同样的错误。

上面的错误是因为 RxAndroid 2.0.1 本身依赖了 RxJava 2.0.1。我们尝试去掉对 RxJava 的依赖,只留下 RxAndroid 。还是会遇到问题。

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
//compile 'io.reactivex.rxjava2:rxjava:2.0.7'
compile 'io.reactivex:rxandroid:1.2.0'
//compile 'io.reactivex:rxjava:1.1.5'

所以使用RxAndroid不能去掉对RxJava的依赖,我是这样使用的。

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.7'

官方也是这样解释的

Because RxAndroid releases are few and far between, it is recommended you also
explicitly depend on RxJava's latest version for bug fixes and new features.

最后,我建议要升级到 RxJava2 的时候必须所有使用的地方都要升级,并且用最新的版本。

2. 新增Flowable

RxJava1 中 Observable 不能很好地支持 backpressure ,会抛出MissingBackpressureException。所以在 RxJava2 中 Oberservable 不再支持 backpressure ,而使用新增的 Flowable 来支持 backpressure 。

Flowable的用法跟原先的Observable是一样的。

3. ActionN 和 FuncN 改名

ActionN 和 FuncN 遵循Java 8的命名规则。
其中,Action0 改名成Action,Action1改名成Consumer,而Action2改名成了BiConsumer,而Action3 - Action9都不再使用了,ActionN变成了Consumer<Object[]>

同样,Func改名成Function,Func2改名成BiFunction,Func3 - Func9 改名成 Function3 - Function9,FuncN 由 Function<Object[], R> 取代。

4. Observable.OnSubscribe 变成 ObservableOnSubscribe

原先RxJava1的写法:

  Observable.create(new Observable.OnSubscribe<String>() {

   @Override
   public void call(Subscriber<? super String> subscriber) {
    subscriber.onNext("hello");
   }

  }).subscribe(new Action1<String>() {

   @Override
   public void call(String s) {
    System.out.println(s);
   }
  });

现在的写法:

  Observable.create(new ObservableOnSubscribe<String>() {

   @Override
   public void subscribe(ObservableEmitter<String> e) throws Exception {
    e.onNext("hello");
   }

  }).subscribe(new Consumer<String>() {

   @Override
   public void accept(String s) {
    System.out.println(s);
   }
  });

5. ObservableOnSubscribe 中使用 ObservableEmitter 发送数据给 Observer

结合上一条,ObservableOnSubscribe 不再使用 Subscriber 而是用 ObservableEmitter 替代。

ObservableEmitter 可以理解为发射器,是用来发出事件的,它可以发出三种类型的事件,通过调用emitter的onNext(T value) onComplete()onError(Throwable error)可以分别发出next事件、complete事件和error事件。 如果只关心next事件的话,只需单独使用onNext()即可。

需要特别注意,emitter的onComplete()调用后,Consumer不再接收任何next事件。

6. Observable.Transformer 变成 ObservableTransformer

原先RxJava1的写法:

 /**
  * 跟compose()配合使用,比如ObservableUtils.wrap(obj).compose(toMain())
  * @param <T>
  * @return
  */
 public static <T> Observable.Transformer<T, T> toMain() {
  return new Observable.Transformer<T, T>() {
   @Override
   public Observable<T> call(Observable<T> tObservable) {
    return tObservable
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread());
   }
  };
 }

现在的写法:

 /**
  * 跟compose()配合使用,比如ObservableUtils.wrap(obj).compose(toMain())
  * @param <T>
  * @return
  */
 public static <T> ObservableTransformer<T, T> toMain() {

  return new ObservableTransformer<T, T>() {

   @Override
   public ObservableSource<T> apply(Observable<T> upstream) {
    return upstream.subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread());
   }
  };
 }

由于新增了Flowable,同理也增加了FlowableTransformer

 public static <T> FlowableTransformer<T, T> toMain() {

  return new FlowableTransformer<T, T>() {

   @Override
   public Publisher<T> apply(Flowable<T> upstream) {
    return upstream.subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread());
   }
  };
 }

7. Subscription 改名为 Disposable

在 RxJava2 中,由于已经存在了 org.reactivestreams.subscription 这个类,为了避免名字冲突将原先的 rx.Subscription 改名为 io.reactivex.disposables.Disposable

刚开始不知道,在升级 RxJava2 时发现 org.reactivestreams.subscription 这个类完全没法做原先 rx.Subscription 的事情:(

顺便说下,Disposable必须单次使用,用完就要销毁。

8. first() 用法改变

官方文档是这么描述的first()的用法

1.x 2.x
first() RC3 renamed to firstElement and returns Maybe<T>
first(Func1) dropped, use filter(predicate).first()
firstOrDefault(T) renamed to first(T) and RC3 returns Single<T>
firstOrDefault(Func1, T) renamed to first(T) and RC3 returns Single<T>

first(Func1)为例,first(Func1)后面还使用了push() ,原先 Rxjava1会这样写

ConnectableObservable<Data> connectableObservable = Observable
   .concat(Observable.from(list))
   .first(new Func1<Data, Boolean>() {
    @Override
    public Boolean call(Data data) {
     return DataUtils.isAvailable(data);
    }
   }).publish();

RxJava2 改成这样

ConnectableObservable<Data> connectableObservable = Observable
   .concat(Observable.fromIterable(list))
   .filter(new Predicate<Data>() {

    @Override
    public boolean test(@NonNull Data data) throws Exception {
     return DataUtils.isAvailable(data);
    }
   }).firstElement().toObservable().publish();

9. toBlocking().y 被 blockingY() 取代

在我的框架中存在着一个Optional类,它跟Java 8的Optional作用差不多,原先是使用RxJava1来编写的。

import rx.Observable;

/**
 * 使用方法:
 *   String s = null;
 *   Optional.ofNullable(s).orElse("default")); // 如果s为null,则显示default,否则显示s的值
 * @author Tony Shen
 *
 */
public class Optional<T> {

 Observable<T> obs;

 public Optional(Observable<T> obs) {
  this.obs = obs;
 }

 public static <T> Optional<T> of(T value) {
  if (value == null) {
   throw new NullPointerException();
  } else {
   return new Optional<T>(Observable.just(value));
  }
 }

 public static <T> Optional<T> ofNullable(T value) {
  if (value == null) {
   return new Optional<T>(Observable.<T>empty());
  } else {
   return new Optional<T>(Observable.just(value));
  }
 }

 public T get() {
  return obs.toBlocking().single();
 }

 public T orElse(T defaultValue) {
  return obs.defaultIfEmpty(defaultValue).toBlocking().single();
 }
}

升级到RxJava2之后,get() orElse() 方法都会报错,修改之后是这样的。

import io.reactivex.Observable;

/**
 * 使用方法:
 *   String s = null;
 *   Optional.ofNullable(s).orElse("default"); // 如果s为null,则显示default,否则显示s的值
 * @author Tony Shen
 *
 */
public class Optional<T> {

 Observable<T> obs;

 public Optional(Observable<T> obs) {
  this.obs = obs;
 }

 public static <T> Optional<T> of(T value) {
  if (value == null) {
   throw new NullPointerException();
  } else {
   return new Optional<T>(Observable.just(value));
  }
 }

 public static <T> Optional<T> ofNullable(T value) {
  if (value == null) {
   return new Optional<T>(Observable.<T>empty());
  } else {
   return new Optional<T>(Observable.just(value));
  }
 }

 public T get() {

  return obs.blockingSingle();
 }

 public T orElse(T defaultValue) {

  return obs.defaultIfEmpty(defaultValue).blockingSingle();
 }
}

10. PublishSubject

包括 PublishSubject 以及各种 Subject(ReplaySubject、BehaviorSubject、AsyncSubject) 都不再支持backpressure。

总结

RxJava2 所带来的变化远远不止这些,以后遇到的话还会继续整理和总结,毕竟我使用的 RxJava2 还是很少的一部分内容。

RxJava2 最好到文档依然是官方文档。如果是新项目到话,可以毫不犹豫地使用RxJava2,如果是在线上已经成熟稳定的项目,可以再等等。对于新手的话,可以直接从 RxJava2 学起,RxJava1 就直接略过吧。对于老手,RxJava2 还是使用原来的思想,区别不大,从 RxJava1 迁移到 Rxjava2 也花不了多少工夫。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • RxJava 1升级到RxJava 2过程中踩过的一些“坑”

    RxJava2介绍 RxJava2 发布已经有一段时间了,是对 RxJava 的一次重大的升级,由于我的一个库cv4j使用了 RxJava2 来尝鲜,但是 RxJava2 跟 RxJava1 是不能同时存在于一个项目中的,逼不得已我得把自己所有框架中使用 RxJava 的地方以及 App 中使用 RxJava 的地方都升级到最新版本.所以我整理并记录了一些已经填好的坑.分享出来供大家参考学习,下面来看看详细的介绍: 填坑记录 1. RxJava1 跟 RxJava2 不能共存 如果,在同一个mo

  • 浅谈springfox-swagger原理解析与使用过程中遇到的坑

    swagger简介 swagger确实是个好东西,可以跟据业务代码自动生成相关的api接口文档,尤其用于restful风格中的项目,开发人员几乎可以不用专门去维护rest api,这个框架可以自动为你的业务代码生成restfut风格的api,而且还提供相应的测试界面,自动显示json格式的响应.大大方便了后台开发人员与前端的沟通与联调成本. springfox-swagger简介 签于swagger的强大功能,java开源界大牛spring框架迅速跟上,它充分利用自已的优势,把swagger集成

  • RxJava入门指南及其在Android开发中的使用示例

    RxJava的GitHub主页,部署部分就没什么好说的了~ https://github.com/ReactiveX/RxJava 基础 RxJava最核心的两个东西是Observables(被观察者,事件源)和Subscribers(观察者).Observables发出一系列事件,Subscribers处理这些事件.这里的事件可以是任何你感兴趣的东西(触摸事件,web接口调用返回的数据...) 一个Observable可以发出零个或者多个事件,知道结束或者出错.每发出一个事件,就会调用它的Su

  • webpack 1.x升级过程中的踩坑总结大全

    前言 大家应该都知道,Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源.因为最近在对博客做SSR,无奈vue ssr demo或例子都是基于webpack2的.博主在webpack1.x上折腾了许久,vue-ssr-server-bundle.json文件生成仍然还是遥遥无期.最后还是乖乖地开始了webpack升级之旅. 本文主要记录升级过程中遇到的一些坑和解决办法,可能有些遗漏了,能记多少记多少吧.话不多说了,来一

  • TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南

    笔者remove TensorFlow总共四次. reinstall anaconda 三次. 安装技巧可以根据这个博主的文章进行安装. https://www.jb51.net/article/184309.htm 我就是用这个教程安装的 因为直接用 pip install安装太慢了 所以在官网CUDA 和cuDNN+清华镜像的TensorFlow来安装比较快. 总结我的几个问题. 一.安装错误 · (1) tensorboard 1.14.0 has requirement setuptoo

  • idea 与 maven 使用过程中遇到的问题及解决方案

    目录 1. maven项目导入idea报ComponentLookupException异常 1.1. 问题描述 1.2.解决方案 2. IDEA无法加载maven本地仓库的文件 2.1.问题描述 2.2.解决方案 3.删除maven下载失败的jar包 3.1. 问题描述 3.2.解决方案 4. 删除_maven.repositories文件 4.1.问题描述 4.2.解决方案 1. maven项目导入idea报ComponentLookupException异常 1.1. 问题描述 最近将ID

  • SpringMail使用过程中的报错解决办法

    SpringMail使用过程中的报错解决办法 1.Unable to locate provider for protocol: smtp –>缺少依赖造成的 <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency> <dependency

  • 浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑

    前言 绝大多数网站都集成了第三方登录,降低了注册门槛,增强了用户体验.最近看了看 QQ 互联上 QQ 登录的接口文档.接入 QQ 登录的一般流程呢,是这样的:先申请开发者 -> 然后创建应用(拿到一组 AppId 和 AppKey)-> 获取 access_token -> 获取 openid -> 调用 openApi 访问或修改用户信息. 然而,从申请个人开发者开始,坑就来了. 1. 申请(个人)开发者 QQ 互联中申请开发者信息的页面,一些重点太过简陋,缺失细节,比如身份证正

  • sql server 2008安装过程中服务器配置出错解决办法

    sql server 2008安装过程中服务器配置出错,求助!!!!!!! 解决方法: 当sql2008安装导向运行到这里时: 请选择:对所有SQL Server 服务使用相同的账号: 但这里不能给他设置自己定义的账号和密码(例如下面设置它的账号为sa,密码为654321)就会发生错误: 解决方法如下图所示: 1.  首先要点击"对所有SQL Server 服务使用相同的账号" 然后会弹出一对话框让我们输入账户和密码:我们点击账户后面的下拉列表从中学则任意一个账户,在这里密码就不用填写

  • 解决vue.js在编写过程中出现空格不规范报错的问题

    找到build文件夹下面的webpack.base.conf.js文件. 然后打开该文件,找到图下这段代码,把他注释掉. 注释掉之后,再进行子页面等编写的时候,空格不规范的情况下也不会再报错啦.因为这个报错对于初学者来说实在头大.哈哈O(∩_∩)O哈哈~ 我标注的这些地方,原本是有严格的空格规范要求的,这些报错真是另人烦躁呀o(╥﹏╥)o 反正我把这个问题解决了,特别开心哒哒哒~~~ 以上这篇解决vue.js在编写过程中出现空格不规范报错的问题就是小编分享给大家的全部内容了,希望能给大家一个参考

随机推荐