谈一个RxJava2的常见用法,一般我们用RxJava2,都会在页面中发起网络请求,在onDestory的时候执行Disposable.dispose。
下面看一个案例:
disposable = Observable
.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
new Thread() {
@Override
public void run() {
try {
emitter.onNext("1==>" + Thread.currentThread().getName());
Thread.sleep(1000);
emitter.onNext("2==>" + Thread.currentThread().getName());
Thread.sleep(1000);
emitter.onNext("3==>" + Thread.currentThread().getName());
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
emitter.onError(new RuntimeException("lmj123"));
}
}.start();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
throwable.printStackTrace();
}
});
我们写一个最简单的RxJava的代码,正常情况下,执行完成,会执行到onError的Consumer,打印出异常堆栈,肯定是不会崩溃的。
假设我们在
emitter.onError(new RuntimeException("lmj123"));
执行前,点击按钮,执行dispose(这里其实就是模仿onDestory,点击感受更直观):
findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("lmj", "onDestroy");
disposable.dispose();
}
});
问题来了:
- 上述代码会崩溃吗,为什么?
- 如果会崩溃,是不是我们最常见的RxJava2页面内操作,onDestory dispose()的写法其实是有风险的?
- 如果2成立,有什么好的处理方案吗?
更多问答 >>
-
每日一问 | 自定义控件测量模式真的和 match_parent,wrap_content 一一对应吗?
2020-03-30 01:01 -
每日一问 | Activity 启动动画对页面打开速度有影响吗?
2020-04-22 22:06 -
每日一问 | Fragment 是如何被存储与恢复的? 有更新
2020-06-07 09:01 -
每日一问 | 上周出现了大规模的github证书不可用的状态...但是真的是github服务器被攻击了么?
2020-04-01 21:49 -
每日一问 | 我们经常用的 String类型,你知道它最大可以放多长的字符串吗?
2020-04-08 23:58 -
每日一问 ViewPager 这个流传广泛的写法,其实是有问题的!
2020-03-26 00:10 -
每日一问 LifeCycle 对于 Lifecycle.Event 为啥不直接分发,而是通过 Lifecycle.State 中转?
2020-04-19 14:42 -
每日一问 今天考察下 Fragment 相关两个不常见 API
2020-03-19 00:55 -
每日一问 | 很久以前有Activity.onResume就是界面可见的说法,这种说法错了多少?
2020-03-15 23:10 -
每日一问 RecyclerView卡片中持有的资源,到底该什么时候释放?
2020-03-10 21:11
首先是会崩溃的, 因为dispose之后代表上游与下游已经断开了,下游已经不接受数据或异常了,此时就会交给全局钩子处理,若没有钩子或钩子又抛出异常,就交给线程的uncaughtexceptionhandler处理,所以有两种方式处理:
赞,学到了~
除了楼上老哥的解决办法,我也说一个 ,在 Application 中设置一下
全局捕获也可以。
参照:https://github.com/ReactiveX/RxJava/issues/6249 https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handlingRx不允许在disponse后再调用onError。我说下处理方案吧。使用tryOnError代替onError。 前者会在发送onError前判断流是否已disponse。
测试消息回复,感觉不处理问题也不大,什么情况下会主动dispose呢,对吧。
1.会崩溃,看onError里面的源码,在执行之前会先判断是否dispose,如果已经dispose会抛出UndeliverableException
2.理论是肯定会存在风险的,即使是在onDestroy dispose()3.个人建议在执行onError之前自己主动去判断dispose是否会好一点之前碰到了这个问题,当时是发出请求后服务器端刚好在重启,然后程序就崩溃了,知道了原因但是不知道要在哪里设置捕获,谢谢1楼的解答
测试回答消息提醒。
RxJava说:你这个new了一个新的线程不归我管!
这是一个反人类设计,在ObservableEmitter里面new了一个新的线程,由于不同的线程,所以dispose以后还是会运行到emitter.onError,这时候就会报已经被cancel/dispose的错误,如果这样:这种情况就不会报错,因为dispose的时候会直接把ObservableEmitter里面的取消的,例子里面的new一个线程的反人类操作,因为新的线程不归RX管理报错是必然的
不是,你可以在subscribe里面执行任何代码,比如我就想用okhttp在里面发个异步请求(相当于new Thread),然后回调通过emitter发射结果出去完全是可以的。 ...查看更多
不是,你可以在subscribe里面执行任何代码,比如我就想用okhttp在里面发个异步请求(相当于new Thread),然后回调通过emitter发射结果出去完全是可以的。
那是什么原因? 源码里面做了判断 取消以后调用不了onNext ,但是调用onError是抛出异常。
我是来测试消息回复的
在subscribeOn(Schedulers.io())的时候RxJava已经把被观察的内容放到子线程里执行了,如果非要再次在里面执行子线程的操作,是不是该用操作符,应为这样实际上就像先拿到第一个接 ...查看更多
在subscribeOn(Schedulers.io())的时候RxJava已经把被观察的内容放到子线程里执行了,如果非要再次在里面执行子线程的操作,是不是该用操作符,应为这样实际上就像先拿到第一个接口的值再去请求第二个接口的情况啊