在RxJava 中,Scheduler
——调度器,至关于线程控制器,RxJava 经过它来指定每一段代码应该运行在什么样的线程。RxJava 已经内置了几个 Scheduler
,它们已经适合大多数的使用场景:java
Schedulers.immediate()
: 直接在当前线程运行,至关于不指定线程。这是默认的 Scheduler
。Schedulers.newThread()
: 老是启用新线程,并在新线程执行操做。Schedulers.io()
: I/O 操做(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler
。行为模式和 newThread()
差很少,区别在于 io()
的内部实现是是用一个无数量上限的线程池,能够重用空闲的线程,所以多数状况下 io()
比 newThread()
更有效率。不要把计算工做放在 io()
中,能够避免建立没必要要的线程。Schedulers.computation()
: 计算所使用的 Scheduler
。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操做限制性能的操做,例如图形的计算。这个 Scheduler
使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操做放在 computation()
中,不然 I/O 操做的等待时间会浪费 CPU。AndroidSchedulers.mainThread()
,它指定的操做将在 Android 主线程运行。
有了这几个 Scheduler
,就可使用 subscribeOn()
和 observeOn()
两个方法来对线程进行控制了。数据库
subscribeOn()
: 指定 subscribe()
所发生的线程,即 Observable.OnSubscribe
被激活时所处的线程。或者叫作事件产生的线程。observeOn()
: 指定 Subscriber
所运行在的线程。或者叫作事件消费的线程。即回调的线程。二者最主要的差异是影响的范围不一样,observeOn is more limited,可是倒是能够屡次调用,屡次改变不一样的接受者所在的schedule,在调用这个函数以后的observable形成影响。而subscribeon则是一次性的,不管在什么地方调用,老是从改变最原始的observable开始影响整个observable的处理。网络
上代码:ide
Observable.just(1, 2, 3, 4) .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程 .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程 .subscribe(new Action1<Integer>() { @Override public void call(Integer number) { Log.d(tag, "number:" + number); } });
上面这段代码中,因为 subscribeOn(Schedulers.io())
的指定,被建立的事件的内容 1
、2
、3
、4
将会在 IO 线程发出;而因为observeOn(AndroidScheculers.mainThread()
) 的指定,所以 subscriber
数字的打印将发生在主线程 。事实上,这种在subscribe()
以前写上两句 subscribeOn(Scheduler.io())
和 observeOn(AndroidSchedulers.mainThread())
的使用方式很是常见,它适用于多数的 『后台线程取数据,主线程显示』的程序策略。函数
而前面提到的由图片 id 取得图片并显示的例子,若是也加上这两句:性能
int drawableRes = ...; ImageView imageView = ...; Observable.create(new OnSubscribe<Drawable>() { @Override public void call(Subscriber<? super Drawable> subscriber) { Drawable drawable = getTheme().getDrawable(drawableRes)); subscriber.onNext(drawable); subscriber.onCompleted(); } }) .subscribeOn(Schedulers.io()) // 指定 subscribe() 发生在 IO 线程 .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程 .subscribe(new Observer<Drawable>() { @Override public void onNext(Drawable drawable) { imageView.setImageDrawable(drawable); } @Override public void onCompleted() { } @Override public void onError(Throwable e) { Toast.makeText(activity, "Error!", Toast.LENGTH_SHORT).show(); } });
那么,加载图片将会发生在 IO 线程,而设置图片则被设定在了主线程。这就意味着,即便加载图片耗费了几十甚至几百毫秒的时间,也不会形成丝毫界面的卡顿。单元测试