BlockingGet阻塞UI线程RxJava 2

10

我正在处理这个问题。

我试图以同步方式调用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();
}

但它仍然被阻止了。

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

谢谢。


一个阻塞调用会一直阻塞,直到有数据返回。不要在UI线程上使用它。要么让另一个线程执行它,要么使用非阻塞调用。 - Gabe Sechan
你的问题是什么?blockingGet() 调用会阻塞 当前 线程,直到数据可用,这是预期的行为。你想要实现什么? - Gergely Kőrössy
@GergelyKőrössy,它没有被释放,导致我的线程卡住了。 - user4671628
1
如果您不想阻塞UI线程,请不要使用带有“blocking”名称的blockingGet - EpicPandaForce
3个回答

20

TL;TR

不要在使用 blockingGet() 方法时加上 observeOn(AndroidSchedulers.mainThread())


Long version

以下代码的输出结果:

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()永远不会返回,所有东西都被卡住了。


在onCreate中,"result"的等待初始化取决于该单个代码的结果,这时主线程会被阻塞,不是吗? - Tamim Attafi

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

问题存在于这些运算符的特定组合中。AndroidSchedulers将代码安排在主线程上运行,然而blockingGet()会阻止该线程上的更多代码执行。简单来说,AndroidSchedulersRxJava的阻塞运算符不能很好地配合使用。
由于Android调度程序可能在可观察对象的构建中使用,这意味着无论你尝试什么,对主线程使用blocking*运算符都容易发生死锁。

0
如果您确实需要在主线程上运行函数并且还需要它是同步的,那么可以像这样做:
  1. 如果这是主线程(Looper.myLooper() == Looper.getMainLooper()),则运行func()

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接