当前位置: 首页 > news >正文

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 共用同一个 SharedViewModelby 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/Activityby viewModels()组件内部私有状态管理
SharedViewModel整个 Activityby activityViewModels()同 Activity 下多 Fragment 通信
父 Fragment ViewModel父 Fragment 及其子 Fragmentby viewModels({ requireParentFragment() })嵌套 Fragment 间的局部数据共享

最佳实践建议

  1. 避免过度共享:非全局数据不要提升到 Activity 级别。
  2. 生命周期安全:子 Fragment 使用 viewLifecycleOwner 观察 LiveData。
  3. 模块化设计:通过父 Fragment ViewModel 隔离无关组件的状态。
  4. 替代方案:复杂场景可结合 RepositoryNavigation ComponentnavGraphViewModels

通过合理选择 ViewModel 作用域,可以清晰管理 Android 多层级 Fragment 架构中的数据流!

http://www.lqws.cn/news/552331.html

相关文章:

  • 栅极驱动器选的好SiC MOSFET高效又安全
  • RabbitMQ-基础篇
  • StarRocks 向量索引如何让大模型“记性更好”?
  • 【Linux】理解进程状态与优先级:操作系统中的调度原理
  • linux安装vscode
  • ABP VNext + 多数据库混合:SQL Server+PostgreSQL+MySQL
  • .NET C# async/定时任务的异步线程池调度方案最大线程数‌ = 处理器核心数 × 250
  • python 文件处理工具(包含文件读写、后缀获取、压缩和解压、文件夹遍历等)
  • C++ STL深度剖析:Stack、queue、deque容器适配器核心接口
  • [Linux]从零开始的STM32MP157移植Ubuntu根文件系统教程
  • 华为云Flexus+DeepSeek征文|基于Dify构建文本/图像/视频生成工作流
  • linux面试常考
  • 【linux】Vm虚拟机ubuntu的接口ip掉了
  • scrapy+django+pyecharts+mysql 实现西安游客行为分析系统大屏_用户画像_空间分析_路线智能推荐
  • Minio入门+适配器模式(实战教程)
  • 鸿蒙5:布局组件
  • libxlsxwriter: 一个轻量级的跨平台的C++操作Excel的开源库
  • HTML表格中<tfoot>标签用法详解
  • 设计模式(策略,工厂,单例,享元,门面)+模板方法
  • 【数据挖掘】贝叶斯分类学习—NaiveBayes
  • git 挑选:git cherry-pick
  • GO 语言学习 之 函数
  • 为何需要防爆平板?它究竟有何能耐?
  • UniApp Vue3 模式下实现页面跳转的全面指南
  • 【笔记】 Docker目录迁移脚本
  • Python 数据分析与可视化 Day 10 - 数据合并与连接
  • 掌握 MySQL 的基石:全面解读数据类型及其影响
  • Swift Moya自定义插件打印日志
  • 【Bluedroid】蓝牙启动之BTM_reset_complete源码解析
  • GitHub Actions 实现 AWS ECS 服务的多集群安全重启方案