You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio 5中RxJava2的PublishSubject未触发subscribe回调问题

问题原因分析

你遇到的问题核心在于PublishSubject的特性:它是一个"热"的Observable,但只会将订阅之后发送的事件推送给观察者,不会保存订阅之前发送的任何事件。

你的代码执行顺序是这样的:

  1. Activity调用viewModelProvider.get(FilmsRxJavaViewModel::class.java),ViewModel被初始化,触发init块:
    • 发送isShowProgress.onNext(true)
    • 调用loadData()发送isShowProgress.onNext(false)
  2. 之后Activity才对isShowProgress进行订阅

这两步的顺序导致ViewModel发送的true和false事件都发生在订阅之前,自然不会被Activity的观察者接收到,所以Logcat里看不到订阅回调的日志。

解决方案

针对这个场景,有两种常见的解决思路:

1. 改用BehaviorSubject替代PublishSubject

BehaviorSubject会保存最后一次发送的事件,当新的观察者订阅时,会立即收到这个最后事件,后续的事件也能正常接收。非常适合这种需要让订阅者获取最新状态的场景。

修改ViewModel的代码:

import io.reactivex.subjects.BehaviorSubject

class FilmsRxJavaViewModel(application: Application) : AndroidViewModel(application) {
    // 可以设置默认值,或者用BehaviorSubject.create(),根据需求选择
    var isShowProgress: BehaviorSubject<Boolean> = BehaviorSubject.createDefault(false)

    init {
        Debug.d(TAG, "init:")
        isShowProgress.onNext(true)
        loadData()
    }

    fun loadData() {
        Debug.d(TAG, "loadData")
        isShowProgress.onNext(false)
    }
}

这样当Activity订阅时,会立即收到ViewModel最后发送的false事件,Logcat就能打印出对应的回调日志了。

2. 调整事件发送的时机

如果不想更换Subject类型,可以调整逻辑,让ViewModel在订阅完成后再发送事件。比如:

  • 修改ViewModel,不在init块里自动调用loadData():
init {
    Debug.d(TAG, "init:")
    // 移除自动调用loadData()的逻辑
}
  • 在Activity订阅完成后,手动触发ViewModel的数据加载:
private fun initLogic() {
    val viewModelProvider = ViewModelProviders.of(this)
    filmsRxJavaViewModel = viewModelProvider.get(FilmsRxJavaViewModel::class.java)
    val dispose = filmsRxJavaViewModel.isShowProgress
        .subscribe { it -> Debug.d(TAG, "initLogic: isShowProgress = $it") }
    // 订阅完成后再触发事件发送
    filmsRxJavaViewModel.isShowProgress.onNext(true)
    filmsRxJavaViewModel.loadData()
}

这样事件都是在订阅之后发送的,观察者就能正常接收到了。

额外注意事项

记得在Activity的onDestroy()方法中取消订阅,避免内存泄漏:

private var dispose: Disposable? = null

private fun initLogic() {
    // ... 其他代码
    dispose = filmsRxJavaViewModel.isShowProgress.subscribe(...)
}

override fun onDestroy() {
    super.onDestroy()
    dispose?.dispose()
}

内容的提问来源于stack exchange,提问作者Alexei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 19:02:56