【问题标题】:PublishSubject blockingLast() hangs Android app and not invokePublishSubject blockingLast() 挂起 Android 应用程序而不调用
【发布时间】:2018-09-14 05:36:56
【问题描述】:

我无法从主题中获取最后一个发出的值

这是我的班级,负责发射和观察电池变化:

class BatteryLevelProvider @Inject constructor(
app: App
) {

private val context: Context = app
private val receiver: PowerConnectionReceiver = PowerConnectionReceiver()

init {
initializeReceiver()
}

private fun initializeReceiver() {
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intentFilter ->
  context.registerReceiver(receiver, intentFilter)
  }
}

companion object {
 val batteryLevelSubject = PublishSubject.create<Int>()
}

fun observeBatteryLevel(): Observable<Int> = batteryLevelSubject.distinctUntilChanged()

fun getCurrentBatteryLevel(): Int {
Timber.d("getCurrentBatteryLevel: ENTERED")
val blockingLast = batteryLevelSubject.blockingLast(0)
Timber.d("getCurrentBatteryLevel: $blockingLast")
return blockingLast
}

inner class PowerConnectionReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
  val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
  val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
  val percentage= (level / scale.toFloat() * 100).toInt()
  batteryLevelSubject.onNext(percentage)
  Timber.d("Battery changed: $percentage")
    }
  }

}

当我调用 获取当前电池电量() 它到达blockingLast永远不会返回值并挂起应用程序。 这是什么原因以及如何正确处理?

【问题讨论】:

    标签: android kotlin rx-java rx-java2


    【解决方案1】:

    subject.blockingLast(0) 的含义如下:获取流完成发射值后的最后一个值,如果它已完成但未发射任何内容,则返回默认值。

    这意味着blockingLast 将等到它收到onComplete 事件,因为只有这样它才能确定流已经结束(并发出最后一个值)。 PublishSubject 创建一个无限流,而您永远不会调用batteryLevelSubject.onComplete 来手动结束流,这就是它永远挂起的原因。

    您可以通过将PublishSubject 更改为BehaviorSubject 轻松解决此问题。它们之间的主要区别在于BehaviorSubject 缓存了最后接收到的值,然后任何人都可以接收到。此外,您需要将batteryLevelSubject.blockingLast(0) 更改为batteryLevelSubject.value 以获取最后一个缓存值(它不会阻止任何内容!)。但请注意,当您还没有放任何东西时,第一次运行时该值可能为 null。您可以通过使用默认值创建 BehaviorSubject 来轻松解决此问题,如下所示:

    val subject = BehaviorSubject.createDefault(0)
    

    【讨论】:

    • 谢谢,但它仍然没有解决我的问题 - batteryLevelSubject.value 仍然阻止应用程序
    • 这很奇怪,因为它不应该。如果您查看 getValue 方法的源代码,您会发现它所做的只是从 AtomicReference 获取值并检查它是否确实是一个值或其他事件。
    • 奇怪,我只需要删除我的应用程序,也许有些东西被缓存了。无论如何谢谢,我接受你的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    相关资源
    最近更新 更多