ViewModel 使用总结:普通、Shared 及嵌套 Fragment 场景
ViewModel 使用总结:普通、Shared 及嵌套 Fragment 场景
1. 普通 ViewModel (by viewModels())
- 作用范围:绑定到单个 Fragment 或 Activity
- 特点:
- 每个 Fragment/Activity 获取的是独立实例
- 适合管理组件私有状态(如 UI 状态、表单数据)
- 生命周期与所属组件一致(Fragment 销毁则 ViewModel 清除)
- 使用场景:
- 单个 Fragment 内部状态管理
- 不需要跨组件共享的数据
代码示例:
class MyFragment : Fragment() {private val myViewModel: MyViewModel by viewModels() // 私有 ViewModel
}
2. SharedViewModel (by activityViewModels())
- 作用范围:绑定到 宿主 Activity,被其下所有 Fragment 共享
- 特点:
- 同一 Activity 内的多个 Fragment 获取的是同一个实例
- 适合跨 Fragment 通信(如主从布局、共享用户数据)
- 生命周期与 Activity 一致(Activity 销毁才清除)
- 使用场景:
- 同 Activity 内多个 Fragment 需要同步数据
- 避免 Fragment 直接相互引用
代码示例:
class FragmentA : Fragment() {private val sharedViewModel: SharedViewModel by activityViewModels() // 共享实例
}class FragmentB : Fragment() {private val sharedViewModel: SharedViewModel by activityViewModels() // 获取同一个实例
}
3. 嵌套 Fragment 中的 ViewModel 作用域控制
当 Fragment 嵌套子 Fragment 时,需根据需求选择作用域:
方案 1:全局共享(Activity 级别)
- 所有层级的 Fragment 共用同一个
SharedViewModel
(by activityViewModels()
) - 适用场景:整个 App 或 Activity 需要共享的数据(如用户登录状态)
方案 2:局部共享(父 Fragment 级别)
- 子 Fragment 通过
requireParentFragment()
获取父 Fragment 的 ViewModel:class ChildFragment : Fragment() {private val parentViewModel: ParentViewModel by viewModels({ requireParentFragment() }) }
- 适用场景:
- 只有父 Fragment 及其子 Fragment 需要共享数据(如 Tab 页状态)
- 模块化设计时隔离数据
方案 3:混合作用域
- 同时使用全局和局部 ViewModel:
// 子 Fragment 中 private val globalVm: GlobalViewModel by activityViewModels() // 全局数据 private val localVm: LocalViewModel by viewModels({ requireParentFragment() }) // 局部数据
总结对比表
类型 | 作用域 | 获取方式 | 适用场景 |
---|---|---|---|
普通 ViewModel | 单个 Fragment/Activity | by viewModels() | 组件内部私有状态管理 |
SharedViewModel | 整个 Activity | by activityViewModels() | 同 Activity 下多 Fragment 通信 |
父 Fragment ViewModel | 父 Fragment 及其子 Fragment | by viewModels({ requireParentFragment() }) | 嵌套 Fragment 间的局部数据共享 |
最佳实践建议
- 避免过度共享:非全局数据不要提升到 Activity 级别。
- 生命周期安全:子 Fragment 使用
viewLifecycleOwner
观察 LiveData。 - 模块化设计:通过父 Fragment ViewModel 隔离无关组件的状态。
- 替代方案:复杂场景可结合
Repository
或Navigation Component
的navGraphViewModels
。
通过合理选择 ViewModel 作用域,可以清晰管理 Android 多层级 Fragment 架构中的数据流!