BlockingGet阻止UI线程RxJava 2

时间:2017-10-06 21:59:53

标签: android multithreading rx-java rx-java2

我正在处理这个问题。

我试图以同步方式调用RxJava,但这样做会导致阻塞主线程。

这是我的代码

   @Override
    public Single<SettingsBundle> getSettings() {
        SettingsBundle settingsModel = mSettingsManager.getSettings();
        return Single.just(settingsModel).map(mSettingsMapper);
    }

这是我的同步电话

   @Override
    public SettingsBundle getSettingsSync() {
        return getSettings().blockingGet();
    }

当调用getSettingsSync主线程被阻止时,但有时它工作正常,更有问题。

我尝试了类似的东西

@Override
public SettingsBundle getSettingsSync() {
    return getSettings()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .blockingGet();
}

但它仍然被阻止。

我做错了什么,我将不胜感激任何帮助。

感谢。

3 个答案:

答案 0 :(得分:6)

<强> TL; TR

永远不要将observeOn(AndroidSchedulers.mainThread())blockingGet()

一起使用

长版

输出:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val result =
                Single.just("Hello")
                .subscribeOn(Schedulers.io())
               // .observeOn(AndroidSchedulers.mainThread())
                .map {
                    println("1. blockingGet `$it` thread: ${Thread.currentThread()}")
                    return@map it
                }
                .blockingGet()
        println("2. blockingGet `$result` thread: ${Thread.currentThread()}")
    }
}

 1. blockingGet `Hello` thread: Thread[RxCachedThreadScheduler-1,5,main]
 2. blockingGet `Hello` thread: Thread[main,5,main]

正如您所见,结果是在主线程(第2行)上生成的,map函数是在RxCachedThreadScheduler线程中执行的。

如果行.observeOn(AndroidSchedulers.mainThread())已取消注释,则blockingGet()永远不会返回,而且所有内容都会被停用。

答案 1 :(得分:3)

.observeOn(AndroidSchedulers.mainThread())
.blockingGet();

此特定运营商组合中存在问题。 AndroidSchedulers安排代码在主线程上运行,但blockingGet()阻止更多代码在该线程上执行。简单地说AndroidSchedulersRxJava的阻塞运算符不能很好地协同工作。

由于android调度程序可能用于构造observable,这意味着无论你尝试做什么,主线程上任何blocking*运算符的使用都将容易出现死锁。

答案 2 :(得分:0)

如果您确实需要在主线程上运行一个函数并且还需要使其同步,那么您可以执行以下操作:

  1. 如果这是主线程(Looper.myLooper() == Looper.getMainLooper()),请运行func()

  2. 如果不在主线程上,则可以使用observeOn(AndroidSchedulers.mainThread())blockingGet()

  3. 的组合