You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fragment中companion object与SharedPreferences传值优劣及性能对比

跨Fragment共享数据方案对比结论

1. 直接在Fragment的companion object中定义共享变量的方式不合理

首先你贴的示例代码存在基础语法错误:val修饰的是只读不可变变量,后续执行ExampleFragment.myValueToShare = 10f的赋值操作会直接编译失败,要支持修改变量必须将val替换为var。

从实现逻辑看,这种写法本身存在很多设计缺陷:

  • 强耦合问题:Fragment的设计目标是可独立复用的UI组件,将共享状态挂载在某个Fragment的伴生对象下,意味着所有访问这个变量的组件都和ExampleFragment强绑定,后续做组件拆分、代码重构时会出现牵一发动全身的问题。
  • 状态不可靠:companion object的成员是类级别的静态单例,生命周期和APP进程完全绑定。如果APP在后台被系统回收内存、进程被杀重启,变量会直接重置为初始值,没有任何状态恢复机制;甚至在屏幕旋转等配置变更触发类重新加载时,也可能出现状态不一致。
  • 内存泄漏风险:如果后续将变量替换为Context、Bitmap、View等持有UI引用的类型,静态单例的长生命周期会导致页面资源无法被正常回收,直接触发内存泄漏。
  • 无并发安全保障:多线程同时读写该变量时没有任何锁防护,很容易出现数据错乱。

2. 该场景下不推荐使用SharedPreferences

SharedPreferences是Android提供的本地持久化键值对存储方案,设计初衷是存储APP重启后仍需保留的轻量配置(比如用户设置的主题开关、字体大小等),完全不适合做运行时跨Fragment的内存数据共享:

  • 存在不必要的IO开销:SP的存储介质是本地磁盘XML文件,首次读取需要解析磁盘文件,写操作不管是异步刷盘的apply还是同步阻塞的commit都会触发磁盘IO,用来做页面间实时传值属于典型的性能浪费。
  • 持久化特性冗余:如果只是传递APP运行期间的临时值,数据写入磁盘后会在进程结束后残留,反而容易引发后续逻辑异常。

3. 两种方式的轻量度对比

companion object定义静态变量的方式远比SharedPreferences轻量,核心原因有两点:

  • 访问链路更短:companion object的变量直接分配在APP进程的堆内存中,读写就是直接的内存寻址操作,没有任何额外中间环节;SP读写需要先初始化SP实例、加载解析磁盘文件生成内存映射、写操作还要等待磁盘刷盘,链路更长、开销更大。
  • 额外成本更低:companion object的变量仅在类第一次加载时初始化一次,没有序列化/反序列化、文件维护、跨进程通信等额外成本;SP需要维护文件句柄、键值对映射表,如果开启多进程模式还要走Binder通信,额外开销会更高。

补充说明:虽然companion object方式性能更好,但它并不是跨Fragment共享数据的推荐方案,正确选型应该匹配业务场景:

  • 同一个Activity下的多个Fragment共享数据:使用绑定Activity生命周期的ViewModel,数据在屏幕旋转等配置变更时不会丢失,不会产生内存泄漏,生命周期和页面完全匹配。
  • 跨页面的全局运行时数据:使用独立的Repository单例类存储,不要把全局变量挂在Fragment/Activity这类UI组件的伴生对象下,避免组件耦合。
  • 只有需要持久化保存、APP重启后仍需保留的数据,才选择SharedPreferences(或其现代替代方案DataStore)。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:36:22