一、测试概述
本测试旨在验证在不同 ViewModelStoreOwner 和 LifecycleOwner 配置下,Activity 和 Fragment 对 LiveData 的观察行为。
核心概念
-
ViewModelStoreOwner: 决定 ViewModel 实例的存储位置和共享范围
- 使用
Activity作为 ViewModelStoreOwner:Activity 和所有使用 Activity 的 Fragment 共享同一个 ViewModel 实例 - 使用
Fragment作为 ViewModelStoreOwner:每个 Fragment 拥有独立的 ViewModel 实例
- 使用
-
LifecycleOwner: 决定 LiveData 观察者的生命周期绑定
- 使用
Activity作为 LifecycleOwner:观察者绑定到 Activity 的生命周期 - 使用
Fragment作为 LifecycleOwner:观察者绑定到 Fragment 的生命周期
- 使用
二、测试场景与结果
场景1:Fragment1 使用 Activity 的 ViewModelStoreOwner 和 LifecycleOwner
setValue 来源: Activity 的 viewModel
测试说明: Activity 调用 setValue,Activity 未 observe
| 组件 | ViewModelStoreOwner | LifecycleOwner | 是否 observe | 观察结果 |
|---|---|---|---|---|
| Activity | Activity | Activity | ❌ 未 observe | - |
| Fragment1 | Activity | Activity | ✅ observe | ✅ 观察到 |
| Fragment2 | Fragment | Fragment | ✅ observe | ❌ 无法观察到 |
结论: Fragment1 与 Activity 共享 ViewModel 实例,可以观察到 Activity 设置的值;Fragment2 使用独立的 ViewModel 实例,无法观察到。
场景2:Fragment1 使用 Activity 的 ViewModelStoreOwner,Fragment 自身的 LifecycleOwner
setValue 来源: Activity 的 viewModel
测试说明: Activity 调用 setValue,Activity 未 observe
| 组件 | ViewModelStoreOwner | LifecycleOwner | 是否 observe | 观察结果 |
|---|---|---|---|---|
| Activity | Activity | Activity | ❌ 未 observe | - |
| Fragment1 | Activity | Fragment | ✅ observe | ✅ 观察到 |
| Fragment2 | Fragment | Fragment | ✅ observe | ❌ 无法观察到 |
结论: Fragment1 虽然使用 Fragment 作为 LifecycleOwner,但因为与 Activity 共享 ViewModel 实例,仍能观察到 Activity 设置的值。
场景3:Fragment1 使用 Fragment 的 ViewModelStoreOwner,Activity 的 LifecycleOwner
setValue 来源: Activity 的 viewModel
测试说明: Activity 调用 setValue,Activity 未 observe
| 组件 | ViewModelStoreOwner | LifecycleOwner | 是否 observe | 观察结果 |
|---|---|---|---|---|
| Activity | Activity | Activity | ❌ 未 observe | - |
| Fragment1 | Fragment | Activity | ✅ observe | ❌ 无法观察到 |
| Fragment2 | Fragment | Fragment | ✅ observe | ❌ 无法观察到 |
结论: Fragment1 使用独立的 ViewModel 实例,即使使用 Activity 作为 LifecycleOwner,也无法观察到 Activity 的 ViewModel 实例的变化。
场景4:Activity 和 Fragment1 都使用 Activity 的 ViewModelStoreOwner 和 LifecycleOwner
setValue 来源: Fragment1 的 viewModel
测试说明: Fragment1 调用 setValue,Activity 也 observe
| 组件 | ViewModelStoreOwner | LifecycleOwner | 是否 observe | 观察结果 |
|---|---|---|---|---|
| Activity | Activity | Activity | ✅ observe | ✅ 观察到 |
| Fragment1 | Activity | Activity | ✅ observe | ✅ 观察到 |
| Fragment2 | Fragment | Fragment | ✅ observe | ❌ 无法观察到 |
结论: Activity 和 Fragment1 共享同一个 ViewModel 实例,当 Fragment1 设置值时,Activity 和 Fragment1 都能观察到变化;Fragment2 使用独立的 ViewModel 实例,无法观察到。
场景5:Fragment1 使用 Fragment 的 ViewModelStoreOwner,Activity 的 LifecycleOwner
setValue 来源: Fragment1 的 viewModel
测试说明: Fragment1 调用 setValue,Activity 也 observe
| 组件 | ViewModelStoreOwner | LifecycleOwner | 是否 observe | 观察结果 |
|---|---|---|---|---|
| Activity | Activity | Activity | ✅ observe | ❌ 无法观察到 |
| Fragment1 | Fragment | Activity | ✅ observe | ✅ 观察到 |
| Fragment2 | Fragment | Fragment | ✅ observe | ❌ 无法观察到 |
结论: Fragment1 使用独立的 ViewModel 实例,当 Fragment1 设置值时,只有 Fragment1 能观察到自己的 ViewModel 变化;Activity 虽然 observe,但因为使用的是不同的 ViewModel 实例,无法观察到 Fragment1 设置的值。
三、关键发现总结
1. ViewModelStoreOwner 的作用
| ViewModelStoreOwner | 效果 |
|---|---|
| Activity | Activity 和所有使用 Activity 的 Fragment 共享同一个 ViewModel 实例 |
| Fragment | 每个 Fragment 拥有独立的 ViewModel 实例,互不影响 |
2. LifecycleOwner 的作用
| LifecycleOwner | 效果 |
|---|---|
| Activity | 观察者绑定到 Activity 的生命周期,Activity 销毁时自动移除观察者 |
| Fragment | 观察者绑定到 Fragment 的生命周期,Fragment 销毁时自动移除观察者 |
3. 观察 LiveData 变化的条件
✅ 能观察到变化的条件:
- 必须使用同一个 ViewModel 实例(通过相同的 ViewModelStoreOwner 获取)
- 必须在该 ViewModel 实例上调用
setValue()或postValue() - 必须在该 ViewModel 实例上调用
observe()注册观察者 - 观察者绑定的 LifecycleOwner 必须处于活跃状态(STARTED 或 RESUMED)
❌ 无法观察到变化的情况:
- 使用不同的 ViewModelStoreOwner 获取 ViewModel(不同的 ViewModel 实例)
- 在错误的 ViewModel 实例上设置值
- 未调用
observe()注册观察者 - 观察者绑定的 LifecycleOwner 处于非活跃状态
4. 测试场景分组说明
| 场景组 | setValue 来源 | Activity 是否 observe | 测试目的 |
|---|---|---|---|
| 场景1-3 | Activity 的 viewModel | ❌ 未 observe | 测试 Activity 设置值,Fragment 观察的情况 |
| 场景4-5 | Fragment1 的 viewModel | ✅ observe | 测试 Fragment 设置值,Activity 和 Fragment 观察的情况 |
四、最佳实践建议
1. 共享数据场景
推荐配置:
- Activity 和需要共享数据的 Fragment 都使用 Activity 作为 ViewModelStoreOwner
- 使用 Activity 或 Fragment 作为 LifecycleOwner 都可以(取决于业务需求)
// Activity
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.data.observe(this) { ... }
// Fragment
viewModel = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)
viewModel.data.observe(this) { ... } // 或 observe(requireActivity()) { ... }
2. 独立数据场景
推荐配置:
- 每个 Fragment 使用 Fragment 自身 作为 ViewModelStoreOwner
- 使用 Fragment 自身 作为 LifecycleOwner
// Fragment
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.data.observe(this) { ... }
3. 注意事项
⚠️ 避免的配置:
- Fragment 使用 Fragment 作为 ViewModelStoreOwner,但使用 Activity 作为 LifecycleOwner(容易造成混淆)
- 在 Activity 中设置值,但 Fragment 使用独立的 ViewModel 实例(无法观察到变化)
五、测试代码示例
场景4 的完整实现(推荐配置)
// Activity
class TestLiveDataActivity : BaseActivity() {
private lateinit var viewModel: TestLiveDataViewModel
override fun initData() {
viewModel = ViewModelProvider(this).get(TestLiveDataViewModel::class.java)
viewModel.testLiveData.observe(this) { value ->
LogUtil.d("TestLiveData", "Activity观察到: $value")
}
}
}
// Fragment1
class TestLiveDataFragment1 : BaseFragment() {
private lateinit var viewModel: TestLiveDataViewModel
override fun initData() {
viewModel = ViewModelProvider(requireActivity()).get(TestLiveDataViewModel::class.java)
viewModel.testLiveData.observe(this) { value ->
LogUtil.d("TestLiveData", "Fragment1观察到: $value")
}
}
}
// Fragment2
class TestLiveDataFragment2 : BaseFragment() {
private lateinit var viewModel: TestLiveDataViewModel
override fun initData() {
viewModel = ViewModelProvider(this).get(TestLiveDataViewModel::class.java)
viewModel.testLiveData.observe(this) { value ->
LogUtil.d("TestLiveData", "Fragment2观察到: $value")
}
}
}
六、总结
- ViewModelStoreOwner 决定数据共享:使用相同的 ViewModelStoreOwner 才能共享同一个 ViewModel 实例
- LifecycleOwner 决定生命周期绑定:观察者会跟随 LifecycleOwner 的生命周期自动管理
- 观察变化的前提:必须在同一个 ViewModel 实例上设置值和观察
- 推荐做法:需要共享数据时,Activity 和 Fragment 都使用 Activity 作为 ViewModelStoreOwner