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 也花不了多少工夫。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
RxJava 1升级到RxJava 2过程中踩过的一些“坑”的更多相关文章
- jenkins配置过程中踩过的一些坑
1,编译通过之后,想要将编译好的war包放到远程服务器上,并解压 unzipBus.sh的脚本如下: #!/bin/bash jar -xvf bus.war 编译后报错:jar:Command no ...
- 细数阿里云在使用 Docker 过程中踩过的那些坑
昨天下午道哥在微信上丢给我一条新闻,看看,我们阿里云支持 Docker 企业版了.我打开一看,果然,阿里云发布了飞天敏捷版,开始支持企业级的 Docker 容器. 美国中部时间4月19日,阿里云在容器 ...
- Jedis使用过程中踩过的那些坑
1. 一个 大坑:若实例化 JedisShardInfo 时不设置节点名称(name属性),那么当Redis节点列表的顺序发生变化时,会发生“ 键 rehash 现象” 使用BTrace追踪redis ...
- 【Fine原创】JMeter分布式测试中踩过的那些坑
最近因为项目需要,研究了性能测试的相关内容,并且最终选用了jmeter这一轻量级开源工具.因为一直使用jmeter的GUI模式进行脚本设计,到测试执行阶段工具本身对资源的过量消耗给性能测试带来了瓶颈, ...
- Jmeter Web 性能测试入门 (七):Performance 测试中踩过 Jmeter 的坑
脚本运行的过程中,大量request抛error,但没有地方能够查看request是因为什么error的. 原因:Jmeter默认禁掉了运行过程中每个request的具体response信息收集,只保 ...
- 使用ffmpeg视频编码过程中踩的一个坑
今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,非常多时候一旦思维定势真的挺难突破的.以下是不对的编码结果: ...
- 记一次使用dubbo过程中版本冲突导致的坑
前言:2019年09月23日临下班,产品的一个变更需求临近尾声阶段.本地测试OK,兴致冲冲的想着发布到测试环境,验证一下没有问题,五分钟结束战斗,明天就开始下个需求了.随在CE(公司的devOps系统 ...
- 谈谈使用echarts过程中踩过的坑
小结: 1. 使用jquery获取json对象遇到的问题 由于自己对ajax用的还不熟练,之前都是拷贝别人的代码拿来用的,这次自己写的时候倒是碰到好多麻烦一一列举如下: 1.1 在$ 与ajax之间还 ...
- 使用NSTimer过程中最大的两个坑
坑1. retain cycle问题. 在一个对象中使用循环执行的nstimer时,若希望在对象的dealloc方法中释放这个nstimer,结局会让你很失望. 这个timer会导致你的对象根本不会被 ...
随机推荐
- Qt Console Application
代码编译完生成的.o文件(又称对象文件,是可执行文件)和链接.o文件形成的.exe可执行文件都保存在“build-Project-Desktop_Qt_5_8_0_GCC_64bit-Debug”中. ...
- 阶段3-团队合作\项目-网络安全传输系统\sprint0-产品规划与设计\第2课-产品功能模型设计
- jquery 规范
使用单引号 不推荐 $("div").html("<img src='1.jpg'>"); 推荐 $('div').html('<img sr ...
- 12.Weblogic 弱口令 && 后台getshell漏洞
利用docker环境模拟了一个真实的weblogic环境,其后台存在一个弱口令,并且前台存在任意文件读取漏洞. 分别通过这两种漏洞,模拟对weblogic场景的渗透. Weblogic版本:10.3. ...
- 玩转Android---组件篇---Intent(意图)
Intent的中文意思是“意图,目的”的意思,可以理解为不同组件之间通信的“媒介”或者“信使”. 目标组件一般要通过Intent来声明自己的条件,一般通过组件中的<intent-filter&g ...
- 事务隔离实现并发控制:MySQL系列之十
一.并发访问控制 实现的并发访问的控制技术是基于锁: 锁分为表级锁和行级锁,MyISAM存储引擎不支持行级锁:InnoDB支持表级锁和行级锁: 锁的分类有读锁和写锁,读锁也被称为共享锁,加读锁的时候其 ...
- B.Grid with Arrows-The 2019 ICPC China Shaanxi Provincial Programming Contest
BaoBao has just found a grid with $n$ rows and $m$ columns in his left pocket, where the cell in the ...
- shell学习(13)- vim
其中部分内容是转载的. 在命令状态下对当前行用== (连按=两次), 或对多行用n==(n是自然数)表示自动缩进从当前行起的下面n行.你可以试试把代码缩进任意打乱再用n==排版,相当于一般IDE里的c ...
- React方法论
按照目前学习进度不定更新 react渲染的效率,看起来是全体的渲染,其实react在虚拟dom上的处理简直完美.它会过滤掉那些原来就有的东西,不去全体地重复渲染一遍. 即将进入实战,React至今的个 ...
- 解决Eclipse导入Gradle项目时在 Building gradle project info 一直卡住
问题描述 在使用 Eclipse 导入 Gradle 项目时一直卡住,不能导入项目 问题解决 解决办法主要有两种:一是直接下载 gradle 离线包,二是修改项目的 ..\gradle\wrapp ...