ViewModel在Fragment中旋转屏幕时清除屏幕上的数值

12

我可能错过了一些明显的东西,但是...我正在DiaryViewModel类中的uiModel中存储数据,由于使用了架构组件,我期望数据能够通过屏幕旋转保留下来,但实际上并没有。我不知道原因在哪里。

这是一个简化的片段。

class DiaryFragment: Fragment() {
    private lateinit var viewModel: DiaryViewModel

    override onCreateView(...) {
        viewModel = ViewModelProviders.of(this).get(DiaryViewModel::class.java)
        viewModel.getModel().observe(this, Observer<DiaryUIModel> { uiModel ->
            render(uiModel)
        })
    }
}

以及对应的视图模型。

class DiaryViewModel: ViewModel() {
    private var uiModel: MutableLiveData<DiaryUIModel>? = null

    fun getModel(): LiveData<DiaryUIModel> {
        if (uiModel == null) {
            uiModel = MutableLiveData<DiaryUIModel>()
            uiModel?.value = DiaryUIModel()
        }

        return uiModel as MutableLiveData<DiaryUIModel>
    }
}

有谁能看出这个简单示例中缺少了什么?现在,当屏幕旋转时,uiModel被设置为null


你使用的支持库版本是什么?v26.1.0 包含对 Lifecycles 的支持(虽然不确定这是否是你遇到的问题的原因)。 - John O'Reilly
@JohnO'Reilly 27.0.2。我也看到了可能是这个问题,但在26版本中已经修复了。猜想我面临的是另一个问题。 - Algar
这可能与片段的生命周期有关......本身并不一定是解决方案,但我通常会将 activity 传递给 ViewModelProviders.of(),但您还需要检查它是否适用于您的特定用例(示例如 https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing 所示)。 - John O'Reilly
确实。我尝试过了,但是没有起作用 :/ 没有任何改变。 - Algar
1个回答

27
问题在于活动如何处理片段的创建。MainActivity 总是每次旋转都会创建一个新的片段,就像这样: MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    supportFragmentManager
        .beginTransaction()
        .replace(overlay.id, DiaryFragment.newInstance())
        .commit()
}

但当检查是否有保存的实例时,它的效果要好得多,例如:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    if (savedInstanceState == null) {
        supportFragmentManager
            .beginTransaction()
            .replace(overlay.id, DiaryFragment.newInstance())
            .commit()
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接