【问题标题】:BlockingGet block UI thread RxJava 2BlockingGet 阻塞 UI 线程 RxJava 2
【发布时间】:2018-03-18 18:38:47
【问题描述】:

我正在处理这个问题。

我正在尝试以同步方式调用 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 线程上使用一个。要么让另一个线程来做,要么使用非阻塞调用。
  • 您的问题到底是什么? blockingGet() 调用将阻塞 current 线程,直到数据可用,这是预期的行为。你想达到什么目标?
  • @GergelyKőrössy ,它没有被释放导致我的线程卡住
  • 如果你不想阻塞 UI 线程,那么不要使用名称中带有“阻塞”的blockingGet

标签: android multithreading rx-java rx-java2


【解决方案1】:

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() 永远不会返回,一切都被卡住了。

【讨论】:

  • 是不是在onCreate中的“result”在等待被这个single的结果初始化时,主线程被阻塞了?
【解决方案2】:
.observeOn(AndroidSchedulers.mainThread())
.blockingGet();

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

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

【讨论】:

    【解决方案3】:

    如果你真的需要一个函数在主线程上运行并且还需要它是同步的,那么你可以这样做:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      相关资源
      最近更新 更多