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
相关产品推荐
相关产品推荐

