初学者在使用RxJava
的过程中,经常搞不清Observable的事件序列和每次操作应该怎样切换线程,切换哪个线程
首先需要搞懂在RxJava
中.subscribeOn()
和 observeOn()
之间的区别:
.subscribeOn()
用来指定Observable
应该操作的调度器(Scheduler
).observeOn()
指定Observable
在一个指定的调度器(Scheduler
)上给观察者发送通知- 默认情况下, 事件序列操作的线程与调用
.subscribe()
的线程一致
没理解?
英文原文: https://medium.com/@diolor/observe-in-the-correct-thread-1939bb9bb9d2#.nn1m7lrb8
翻译: hanks
注: 不是完全翻译,添加了具体例子
例子
1.主线程 / .subscribe() 线程
在 Activity的 onCreate()
(主线程) 方法中添加以下代码:
1 | Observable.just(1,2,3) |
调用情况如下:
实验:
1 | Observable.just(1,2,3) |
输出结果:
1 | 12-06 16:14:39.225 15603-15603/com.hanks.rxsearch I/RxThread: doOnNext:1, run In :main |
2. .subscribeOn()
即使你在主线程中添加下面的代码,但是整段代码将运行在 .subscribeOn()
定义的线程上
1 | Observable.just(1,2,3) |
实验:
1 | Observable.just(1,2,3) |
输出结果:
1 | 12-06 16:13:17.717 14294-14319/com.hanks.rxsearch I/RxThread: doOnNext:1, run In :RxNewThreadScheduler-1 |
3. .observeOn()
加入在主线程中添加下面的代码,首先 Observable
将在 .subscribe()
的线程上创建,但是 .observeOn()
方法被调用之后,代码将运行在指定的线程上:
1 | Observable.just(1,2,3) |
实验:
1 | new Thread() { |
输出结果:
1 | 12-06 16:18:06.493 18584-18606/com.hanks.rxsearch I/RxThread: doOnNext:1, run In :Thread-155 |
3. Combined logic
由于操作可以被组合使用,于是有了下面的代码:
1 | Observable.just(1,2,3) |
实验:
1 | new Thread() { |
输出结果:
1 | 12-06 16:19:53.066 20247-20274/com.hanks.rxsearch I/RxThread: doOnNext:1, run In :RxNewThreadScheduler-1 |
Tips / Gotchas:
1. “UI线程运行异常”
1 | Observable.just(1,2,3) |
obviously.
2. 逻辑处理放在后台(newThread)
错误姿势:
1 | Observable.just(1,2,3) |
实验:
1 | new Thread() { |
输出结果:
1 | 12-06 16:43:00.181 8161-8190/com.hanks.rxsearch I/RxThread: doOnNext:Android-Picasso, run In :RxNewThreadScheduler-1 |
正确姿势:
1 | Observable.just(1,2,3) |
第二段代码中 flatMap
(或者其他逻辑处理)将运行在后台线程, 如果是在Android中,这样做不会阻塞UI,阻塞UI的话有可能导致ANR之类的异常。这跟 AsyncTask
中的 doInBackground()
类似,在 doInBackground()
中做耗时操作
实验:
1 | new Thread() { |
输出结果:
1 | 12-06 16:41:27.025 6812-6839/com.hanks.rxsearch I/RxThread: doOnNext:Android-Picasso, run In :RxNewThreadScheduler-1 |
3. 最早的 .subscribeOn()
生效
看下面的代码:
1 | Observable.just(1,2,3) |
Observable
的创建和 .subscribeOn()
的调用都将在 thread1 上面执行,所以没有必要多次调用 .subscribeOn()
,因为只有第一次的是有用的。
实验:
1 | new Thread() { |
输出结果
1 | 12-06 16:51:17.581 15622-15652/com.hanks.rxsearch I/RxThread: doOnNext:Android-Picasso, run In :RxNewThreadScheduler-1 |
实验
1 | new Thread() { |
输出结果
1 | 12-06 16:52:13.378 16424-16454/com.hanks.rxsearch I/RxThread: doOnNext:Android-Picasso, run In :RxCachedThreadScheduler-2 |
Android
Rxjava
Rxandroid
文章出处 (https://hanks.xyz)