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

如何在Android ViewModel中结合RxJava正确处理屏幕方向变化?

如何结合RxJava正确处理ViewModel中的屏幕方向变化?

嘿,我来帮你捋清楚这个问题——你当前的代码有个核心问题:把liveData和disposables放在了companion object里,这会让它们变成静态全局变量,完全违背了ViewModel的生命周期设计初衷。静态变量不会随着ViewModel的重建/销毁而变化,不仅容易造成内存泄漏,还会在多个ViewModel实例之间共享数据,产生意想不到的bug。

下面是正确的处理方式,分步骤来:

1. 将LiveData和Disposables改为ViewModel成员变量

ViewModel本身就是为了在屏幕旋转等配置变化时保留数据和任务的,所以这些变量应该作为ViewModel的普通成员,而非静态全局变量:

class DummyViewModel : ViewModel() {
    // 跟随ViewModel生命周期的成员变量
    val liveData: MutableLiveData<String> = MutableLiveData()
    private val disposables = CompositeDisposable()

    fun test() {
        disposables.add(
            Observable.interval(1, TimeUnit.SECONDS)
                .map { it.toString() }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { liveData.value = it }
        )
    }

2. 在ViewModel销毁时清理RxJava订阅

当页面真正被销毁(比如用户退出应用),ViewModel会调用onCleared()方法,这时候必须清空所有RxJava订阅,防止内存泄漏:

override fun onCleared() {
        super.onCleared()
        disposables.clear() // 取消所有订阅,避免泄漏
    }
}

3. 在UI层正确观察LiveData

在Activity或Fragment中,要用viewLifecycleOwner来观察LiveData,这样订阅会自动跟随UI组件的生命周期,屏幕旋转后会自动重新绑定,不会丢失数据:

class MyFragment : Fragment() {
    private lateinit var viewModel: DummyViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // 获取ViewModel实例,配置变化时会复用同一个实例
        viewModel = ViewModelProvider(this).get(DummyViewModel::class.java)
        
        // 观察LiveData,自动感知UI生命周期
        viewModel.liveData.observe(viewLifecycleOwner) { countText ->
            // 这里更新你的UI,比如设置TextView文本
            // textView.text = countText
        }
        
        // 启动定时任务
        viewModel.test()
        
        return inflater.inflate(R.layout.fragment_my, container, false)
    }
}

为什么这样处理有效?

  • 屏幕旋转时,ViewModel不会被销毁,RxJava的定时任务会继续运行,LiveData也会保留之前的计数。新的UI实例会自动观察到LiveData的最新值,实现无缝的UI衔接。
  • 当页面彻底销毁时,onCleared()会触发,disposables.clear()会取消所有RxJava订阅,避免订阅持有UI组件的引用导致内存泄漏。
  • 去掉静态变量后,每个ViewModel实例都有独立的LiveData和订阅池,不会和其他页面的实例产生数据干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:41:54