当前位置:   article > 正文

android线程切换原理,RxJava 系列 (四)RxJava 线程切换原理

android rxjava线程切换

前言

理解线程切换原理有什么意义?

可以清楚的知道这个线程切换操作会影响到哪些代码的执行线程,不会影响到哪些代码的执行线程

灵活运用线程切换来实现复杂的应用场景

有利于在发生线程相关的问题时进行调试

不指定线程

举个栗子

由 id 取得图片并显示

由指定的一个 drawable 文件 id drawableRes 取得图片,并显示在 ImageView 中,并在出现异常的时候打印 Toast 报错:

int drawableRes = ...;

ImageView imageView = ...;

Observable.create(new OnSubscribe() {

@Override

public void call(Subscriber super Drawable> subscriber) {

Drawable drawable = getTheme().getDrawable(drawableRes));

subscriber.onNext(drawable);

subscriber.onCompleted();

}

}).subscribe(new Observer() {

@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();

}

});

RxJava 遵循的是线程不变的原则

在哪个线程调用 subscribe(),就在哪个线程生产事件( onSubscribe.call() )和消费事件(subscriber.onNext())

回顾上一节subscribe()的内部实现,就知道整个调用都是在当前线程直接就调用完成了,没有线程的切换

subscribeOn() 和 observeOn()

int drawableRes = ...;

ImageView imageView = ...;

Observable.create(new OnSubscribe() {

@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() {

@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();

}

});

subscribeOn() 控制事件产生的线程,即onSubscribe.call()执行的线程

observeOn()控制事件消费的线程,即(subscriber.onNext())执行的线程

How?

我们一个一个来说。

subscribeOn()

subscribeOn用的是和lift类似的原理,不过不是直接使用的lift,结合lift的原理,简单来说:

1af314fca7cb

切换线程的时机:

把你调用上一层的observable 的onSubscribe.call()来发送事件的操作放在你指定的Scheduler对应的线程来调用,从而达到切换线程的目的

多个 subscribeOn()

Observable.create(onSubscribe)

.subscribeOn(Schedulers.io())

.map(mapOperator)

.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程

.subscribe(subscriber);

此时 onSubscribe.call()会执行在哪个线程?

当使用了多个 subscribeOn() 的时候,第一个 subscribeOn() ,也就是离最初的Observable最近的那个会决定事件产生的线程。

下面的那些subscribeOn()也会执行线程切换,但是因为最终会被第一个subscribeOn()切换回来,所以并没有起到实质性作用。

多个 subscribeOn()没有任何有意义的使用场景吗?

doOnSubscribe()

多个 subscribeOn()的一个有意义的使用场景

Observable.create(onSubscribe)

.subscribeOn(Schedulers.io())

.doOnSubscribe(new Action0() {

@Override

public void call() {

progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行

}

})

.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程

.subscribe(subscriber);

doOnSubscribe()与onStart()对比

相同点:

都是在subscribe()之后,事件发送之前被调用,用于做一些准备工作

不同点:

onStart()是在subscribe()被调用的线程调用,不能指定线程。所以onStart()不适合做对线程有要求的操作,比如更新UI

doOnSubscribe() 可以使用subscribeOn()来指定线程。

为什么可以使用subscribeOn()来指定线程

doOnSubscribe跟其他的操作符有点不一样,一般的操作符的操作是在事件发送之后执行的,是对事件的处理,而doOnSubscribe的操作是在subscribe()调用之后从下往上通知的过程中执行的,所以可以用subscribeOn()来指定线程。

observeOn()

observeOn()内部使用的是lift,在它对应的Operator里完成的线程切换。

参考上一节举得Operator的例子

1af314fca7cb

切换线程的时机:在往下一层发送事件的时候切换线程

这里的subscriber指的是observeOn()下一层的subscriber,并不一定是最终的subscriber

多个 observeOn()

Observable.just(1, 2, 3, 4)

.observeOn(Schedulers.newThread())

.map(mapOperator) // 新线程,由 observeOn() 指定

.observeOn(Schedulers.io())

.map(mapOperator2) // IO 线程,由 observeOn() 指定

.observeOn(AndroidSchedulers.mainThread)

.subscribe(subscriber); // Android 主线程,由 observeOn() 指定

多个observeOn可以多次切换线程,会影响到它下一层的操作的执行线程

多个subscribeOn() 和 observeOn() 混合使用的一个复杂示例

1af314fca7cb

subscribeOn() 和 observeOn() 一般的结合使用示例

一般情况下我们的使用是下面这个样子:

Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定

.subscribeOn(Schedulers.io())

.observeOn(Schedulers.newThread())

.map(mapOperator) // 新线程,由 observeOn() 指定

.observeOn(Schedulers.io())

.map(mapOperator2) // IO 线程,由 observeOn() 指定

.observeOn(AndroidSchedulers.mainThread)

.subscribe(subscriber); // Android 主线程,由 observeOn() 指定

一个subscribeOn来指定事件发送的线程,中间若干个observeOn来指定事件处理和最终事件消费的线程。

参考文献

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号