You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android屏幕旋转时ViewModel被重建?求状态保留解决方案

嘿,这个问题挺典型的,我来帮你理清楚:

一、这种ViewModel销毁属于Android正常行为吗?

答案是肯定的,这是系统的正常运作逻辑。

ViewModel的生命周期和它的ViewModelStoreOwner(这里就是你的Activity)绑定,但有个关键区别:只有当Activity因为配置变更(比如屏幕旋转、语言切换)被销毁时,ViewModel才会被保留下来供新的Activity实例复用。但如果Activity是因为系统内存回收(当App处于后台时,系统为释放资源可能会销毁后台Activity实例)而被销毁,ViewModel会随之触发onCleared()——因为此时系统认为这个Activity及其关联状态已经不需要保留了。

你遇到的流程本质是:后台时Activity已被系统标记为可回收,旋转屏幕的操作触发了Activity重建,但原ViewModel的Owner已因非配置变更原因被销毁,所以ViewModel被清理,新的Activity实例会创建新的ViewModel。

二、推荐的状态保留方案

针对这种场景,有几种靠谱的方案可以选择:

  • SavedStateHandle(官方推荐):这是和ViewModel配套的官方工具,专门解决进程回收或配置变更后的状态保留问题。它会把数据存到Bundle里,系统自动处理持久化和恢复。用法很简单,在ViewModel构造函数中注入SavedStateHandle,然后通过它存取数据:
class MyViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    // 用LiveData自动观察状态变化
    val userInfo = savedStateHandle.getLiveData<UserInfo>("user_info")

    // 手动保存数据
    fun saveUserInfo(info: UserInfo) {
        savedStateHandle.set("user_info", info)
    }
}

不管是配置变更还是进程回收,只要数据能被序列化,都能通过它恢复。

  • 本地持久化存储:如果数据需要长期保留或数据量较大,可以用Room数据库、SharedPreferences、文件存储等方式。比如在ViewModel的onCleared()方法里保存数据,在ViewModel初始化时读取恢复。这种方式适合需要持久化的业务数据,比如用户的离线缓存。

  • Application级ViewModel:如果你的状态需要在整个App生命周期内共享,不受单个Activity销毁影响,可以创建一个绑定到Application的ViewModel。这样只要App进程还在,ViewModel就会一直存在。不过要注意不要在里面存过多数据,避免内存泄漏。

  • WorkManager(针对后台任务):如果是需要在后台持续执行的任务(比如上传文件、同步数据),可以用WorkManager。它能保证任务即使在进程被回收后也能继续执行,完成后再回调通知App更新状态,避免任务丢失。

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

火山引擎 最新活动