您的位置:首页 > 文旅 > 美景 > 云匠网可能会遇到哪些问题_哈尔滨网站建设渠道_百度今日数据_关键词竞价排名名词解释

云匠网可能会遇到哪些问题_哈尔滨网站建设渠道_百度今日数据_关键词竞价排名名词解释

2025/5/11 14:45:59 来源:https://blog.csdn.net/2301_80329517/article/details/146691526  浏览:    关键词:云匠网可能会遇到哪些问题_哈尔滨网站建设渠道_百度今日数据_关键词竞价排名名词解释
云匠网可能会遇到哪些问题_哈尔滨网站建设渠道_百度今日数据_关键词竞价排名名词解释

引言:为什么开发者需要ViewModel?

在Android开发中,屏幕旋转导致页面重建是开发者最头疼的问题之一。 

传统方案通过onSaveInstanceState保存数据,但存在序列化性能瓶颈和数据量限制(Bundle最大1MB)。 

而ViewModel的诞生,通过“生命周期穿透”能力,彻底解决了配置变更导致的数据丢失问题。 

但它的实现原理究竟是什么?本文将揭开其底层三大黑科技。

一、HolderFragment:寄生在Activity中的“数据保险箱”

原理剖析  

当调用ViewModelProviders.of(activity)时,系统会动态注入一个无UI的HolderFragment。这个Fragment的setRetainInstance(true)属性,使其在Activity重建时仍存活于内存中,其内部通过ViewModelStore对象缓存所有ViewModel实例。  

 

源码级实现(以AndroidX 2.5.1为例):  

// HolderFragment关键代码
publicclassHolderFragmentextendsFragment {privateViewModelStoremViewModelStore=newViewModelStore();@OverridepublicvoidonCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setRetainInstance(true); // 关键黑科技!}public ViewModelStore getViewModelStore() {return mViewModelStore;}
}

此设计让ViewModelStore与Activity生命周期解耦,实现跨配置变更的数据持久化。 

 扩展:

ViewModel生命周期穿透(破解内存泄漏困局)

高频面试题:

"为什么Fragment中获取的ViewModel会和Activity共享?如何实现作用域隔离?"  

技术解析:  

  1. 1. 源码级透视:

// 关键源码路径:androidx.fragment.app.FragmentViewModelLazy.kt
HolderFragment().apply {fragmentManager.beginTransaction().add(this, HOLDER_TAG).commitNow()
}
  • ViewModelProvider通过HolderFragment持有ViewModel实例
  • FragmentManager通过FragmentTransaction将HolderFragment绑定到宿主的生命周期
  • 2. 避坑指南:

  • 错误用法:在onCleared()中调用context引发内存泄漏
  • 正确方案:通过AndroidViewModel+ApplicationContext注入

ViewModel的"僵尸复活"机制(字节跳动压轴题)

场景还原:某电商App在屏幕旋转后购物车数据丢失,候选人无法解释ViewModel为何能存活

技术拆解

  1. 底层原理:
    • ViewModel通过HolderFragment实现生命周期隔离(源码见ViewModelStoreOwner

    • 数据存储依赖onRetainNonConfigurationInstance()方法实现跨配置保存

  2. 高频误区:
    • “ViewModel是单例模式”(错误率78%)

    • “ViewModel可以直接持有Context”(会导致内存泄漏)

  3. 解决方案:
// 正确获取ViewModel实例  
val viewModel: MyViewModel by viewModels(  factoryProducer = { CustomFactory() }  
)  

避坑指南
FragmentManager.findFragmentByTag("androidx.lifecycle.ViewModelProvider.Default")可查看HolderFragment状态

二、ViewModelStoreOwner:多组件共享的“数据枢纽”

场景痛点  

传统开发中,Activity与Fragment间的数据传递需要通过Bundle或接口回调,而ViewModel通过ViewModelStoreOwner接口,允许不同组件共享同一ViewModel实例。  

 

实现技巧  

  • 通过扩展ViewModelProvider的owner参数,支持Activity/Fragment/Navigation图等不同作用域
  • 在Fragment中调用ViewModelProviders.of(parentFragment),可获取父容器的ViewModel

 

案例演示:  

// 在Fragment中获取Activity级别的ViewModel
val sharedModel: SharedViewModel by viewModels(requireActivity())

这种设计使得跨组件通信的代码量减少50%以上。 

 


 

三、SavedStateHandle:进程级重建的“最后防线”

突破性能力  

ViewModel默认只能抵御配置变更,但进程被系统杀死时数据仍会丢失。通过集成SavedStateHandle,可将数据写入系统管理的Bundle,实现跨进程销毁的数据恢复。  

技术实现:  

class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {val liveData: MutableLiveData<String> = savedStateHandle.getLiveData("key")init {savedStateHandle.setSavedStateProvider("key") { Bundle().apply { putString("key", liveData.value) }}}
}

底层通过AbstractSavedStateViewModelFactory,在ViewModel初始化时自动注入SavedStateHandle对象。 

 


 

高频面试题深度解析

Q1:ViewModel与onSaveInstanceState有何本质区别?

答:  

  • 作用范围:ViewModel适用于大数据对象(如图片列表),而Bundle适合存储轻量级状态(如页面滚动位置)
  • 生命周期:ViewModel存活到组件完全销毁(如Activity调用finish()),而Bundle仅在临时重建时有效
  • 性能对比:ViewModel通过内存缓存避免序列化开销,性能提升约30倍

 

Q2:如何实现自定义生命周期的ViewModel?

进阶方案:  

  1. 1. 继承ViewModel并重写onCleared()

  2. 2. 通过ViewModelProvider.Factory注入自定义作用域

  3. 3. 使用LifecycleObserver监听特定生命周期事件

public class CustomViewModel extends ViewModel {@Overrideprotected void onCleared() {// 释放资源}
}

总结:ViewModel的三大应用场景

  1. 1. 跨屏幕旋转:HolderFragment + ViewModelStore机制

  2. 2. 跨组件通信:ViewModelStoreOwner的多级作用域控制

  3. 3. 跨进程恢复:SavedStateHandle与Bundle的深度集成

感谢观看!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com