Android Jetpack原理相关面试题分享(三)

256 阅读2分钟

一、ViewModel 生命周期穿透3种黑科技实现

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

一文带你吃透HolderFragment实现ViewModel的生命周期穿透!

原理剖析:

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

示例代码:

class HolderFragment : Fragment() {
    private val viewModelStore = ViewModelStore()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        retainInstance = true // 关键:跨配置变更保留
    }

    // 暴露 ViewModelStore 给宿主 Activity
    fun getCustomViewModelStore() = viewModelStore

    override fun onDestroy() {
        super.onDestroy()
        viewModelStore.clear() // 清理资源
    }
}
  • 此设计让ViewModelStore与Activity生命周期解耦,实现跨配置变更的数据持久化

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

场景痛点:

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

实现技巧:

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

示例代码:

// 在Fragment中获取Activity级别的ViewModel  
val sharedModel: SharedViewModel by viewModels(requireActivity())
  • 该设计使得跨组件通信的代码量可减少50%以上。

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

突破性能力:

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

实现的示例代码:

class StoreViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {  
    val liveData: MutableLiveData<String> = savedStateHandle.getLiveData("key")  
      
    init {  
        savedStateHandle.setSavedStateProvider("key") {   
            Bundle().apply { putString("key", liveData.value) }  
        }  
    }  
}
  • 底层通过AbstractSavedStateViewModelFactory,在ViewModel初始化时自动注入SavedStateHandle对象。

二、Jetpack相关组件的高频面试题

2.1、ViewModelonSaveInstanceState有何本质区别?

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

2.2、如何实现自定义生命周期的ViewModel?

实现方案:

  • 1). 继承ViewModel并重写onCleared()
  • 2). 通过ViewModelProvider.Factory注入自定义作用域
  • 3). 使用LifecycleObserver监听特定生命周期事件

示例代码:

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

三、ViewModel的三大应用场景

  1. 跨屏幕旋转HolderFragment + ViewModelStore机制
  2. 跨组件通信ViewModelStoreOwner的多级作用域控制
  3. 跨进程恢复SavedStateHandleBundle的深度集成

更多分享

  1. Android Jetpack相关面试题分享(一)
  2. Android Jetpack相关面试题分享(二)
  3. Android 架构以及优化相关面试题分享
  4. Android Kotlin协程相关面试题分享
  5. Android 互联网大厂,高频重点面试题集分享(一)