心里种花,人生才不会荒芜,如果你也想一起成长,请点个关注吧。
大家好,我是稳稳,一个曾经励志用技术改变世界,现在为随时失业做准备的中年奶爸程序员,与你分享生活和学习的点滴。
连续熬夜真是吃不消啊!加油!加油!
在Android开发中,屏幕旋转导致页面重建是开发者最头疼的问题之一。
传统方案通过onSaveInstanceState保存数据,但存在序列化性能瓶颈和数据量限制(Bundle最大1MB)。
而ViewModel的诞生,通过“生命周期穿透”能力,彻底解决了配置变更导致的数据丢失问题。
但它的实现原理究竟是什么?本文将揭开其底层三大黑科技。
原理剖析
当调用ViewModelProviders.of(activity)时,系统会动态注入一个无UI的HolderFragment。这个Fragment的setRetainInstance(true)属性,使其在Activity重建时仍存活于内存中,其内部通过ViewModelStore对象缓存所有ViewModel实例。
源码级实现(以AndroidX 2.5.1为例):
// HolderFragment关键代码
publicclassHolderFragmentextendsFragment {
privateViewModelStoremViewModelStore=newViewModelStore();
@Override
publicvoidonCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); // 关键黑科技!
}
public ViewModelStore getViewModelStore() {
return mViewModelStore;
}
}
此设计让ViewModelStore与Activity生命周期解耦,实现跨配置变更的数据持久化。
场景痛点
传统开发中,Activity与Fragment间的数据传递需要通过Bundle或接口回调,而ViewModel通过ViewModelStoreOwner接口,允许不同组件共享同一ViewModel实例。
实现技巧
案例演示:
// 在Fragment中获取Activity级别的ViewModel
val sharedModel: SharedViewModel by viewModels(requireActivity())
这种设计使得跨组件通信的代码量减少50%以上。
突破性能力
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对象。
答:
进阶方案:
public class CustomViewModel extends ViewModel {
@Override
protected void onCleared() {
// 释放资源
}
}
掌握这些黑科技,不仅能写出更健壮的代码,还能在面试中展现源码级原理理解。建议结合AndroidX最新源码(如ViewModelKt.kt)深入实践,让你的架构设计能力再上一个台阶!
本文部分原理分析基于AndroidX 2.5.1源码,更多实现细节可查看官方文档。
END