Jetpack 系列文章都是在学习时候的笔记
写文章的思路是从想到什么问题,到解释这个问题来进行表述的.
不建议通篇阅读, 关心那个看对应的实现即可.
核心类定义:
ViewModelStoreOwner:
interface ViewModelOwner{
val viewModelStore: ViewModelStore
}
ViewModelProvider: ViewModel 的提供商, 构造函数中需要提供 Factory 和 Extras
class ViewModelProvider{
public constructor(owner: ViewModelStoreOwner){
// defaultFactory 传 owner 是判断是会否是 HasDefaultViewModelProviderFactory,
// 取 Activity 携带 SaveStateViewModelFactroy
// defaultCreationExtral 传 owner 是判断是会否是 HasDefaultViewModelProviderFactory,
// 取 Activity 携带 默认参数, 一般会有 application, 和宿主自身的引用.
this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtral(owner))
}
public constructor(owner: ViewModelStoreOwner, factory: Factory){
this(owner.viewModelStore, factory, defaultCreationExtral(owner))
}
public constructor(store: ViewModelStore, factory: Factory, extral: CreateExtras){}
}
Factory: ViewModel 的创建工厂, 常使用到的有 NewInstanceFactory(默认实现) AndroidViewModelFactory(AndroidViewModel 的创建工厂) InitializerViewModelFactory(带参数的构造器) SaveStateViewModelFactory
interface Factory{
public fun <T: ViewModel> create(modelClass: Class<T>): T{}
public fun <T: ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T{}
companion object{
// 带参数创建
fun from(varrag initializers: ViewModelInitializer<*>): Factory = InitializerViewModelFactory(*initializers)
}
}
// 定义 key
object IdKey: CreateExtras.Key<Int>
object NameKey: CreateExtras.key<String>
// 定义 ViewModel
class TestViewModel(val id: Int, val name: String): ViewModel()
// 创建 Factory
val factory = viewModelFactory{
initializer{
val id = this[IdKey]?:error("id error.")
val name = this[NameKey]?:error("name error.")
TestViewModel(id, name)
}
}
// 创建 extras
val extras = MutableCreationExtras().apply{
this[IdKey] = 1
this[NameKey] = "Tom"
}
// 创建 viewModel
val viewModel: TestViewModel = factory.create(TestViewModel::class, extras)
需要搞清楚的问题:
1: ViewModel 的创建方式是什么?
ViewModelProvider(this)[xxx::class.java]
provider#get() → store 中取 → 取 Extras → 调用factory#create → 在 store 中存储
核心是通过两步(1): 创建 ViewModelProvider. (2) 调用 ViewModelProvider 的 get 方法中调用了 factory 的 Create以此来创建 ViewModel.
以上点中核心类有如下几个:
ViewModelProvider ViewModelStore ViewModelStoreOwner Factory
-
ViewModelProvider:有三个缺省的构造方法. 已经两个get函数,如果存在即返回, 如果不存在, 则调用factory进行创建.// 完整构造函数 constructor( private val store: ViewModelStore, private val factory: Factory, private val defaultCreationExtras: CreationExtras = CreationExtras.Empty, ) // 默认构造函数 -> 只有 ViewModelStoreOwner public constructor( owner: ViewModelStoreOwner ) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner)) // 传入 ViewModelStoreOwner 加上 Factory 的构造函数 public constructor(owner: ViewModelStoreOwner, factory: Factory) : this( owner.viewModelStore, factory, defaultCreationExtras(owner) ) // 符号改写的 get 方法. public open operator fun <T : ViewModel> get(modelClass: Class<T>): T { val canonicalName = modelClass.canonicalName ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels") return get("$DEFAULT_KEY:$canonicalName", modelClass) } public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T { val viewModel = store[key] if (modelClass.isInstance(viewModel)) { (factory as? OnRequeryFactory)?.onRequery(viewModel!!) return viewModel as T } else { // 空实现. if (viewModel != null) { } } val extras = MutableCreationExtras(defaultCreationExtras) extras[VIEW_MODEL_KEY] = key // 塞入 key. return try { factory.create(modelClass, extras) } catch (e: AbstractMethodError) { factory.create(modelClass) }.also { store.put(key, it) } } -
ViewModelStore:一个封建的 map. 封装的意义在于(1): 提供了 clear 方法, 方便所有的 ViewModel 的清空.(2): put 操作, 对于之前存在 viewModel 进行清空. clear 和 onCleared 分别是系统自己调用的和给外部调用的, clear 会调用都 onCleared.open class ViewModelStore { private val map = mutableMapOf<String, ViewModel>() @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) fun put(key: String, viewModel: ViewModel) { val oldViewModel = map.put(key, viewModel) oldViewModel?.onCleared() } @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) operator fun get(key: String): ViewModel? { return map[key] } @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) fun keys(): Set<String> { return HashSet(map.keys) } fun clear() { for (vm in map.values) { vm.clear() } map.clear() } } -
ViewModelStoreOwner: 提供了一个返回ViewModelStore的接口. 也就是说实现了ViewModelStoreOwner的都需要提供用来存储ViewModel的集合. 这样ViewModelStoreOwner都可以拿到对应属于自己的ViewModel的存储对象.interface ViewModelStoreOwner { val viewModelStore: ViewModelStore } -
Factory: 提供了创建ViewModel的方式, 核心方法在Create中. 在ViewModelProvider中提供调用.主要的实现有:NewInstanceFactory(默认实现, 只创建不含 extra 的 ViewModel)AndroidViewModelFactory承担了大部分的创建任务.SavedStateViewModelFactoryComponentActivity的默认使用,内部调用还是AndroidViewModelFactory, 提供了 Application 的绑定.public interface Factory { public fun <T : ViewModel> create(modelClass: Class<T>): T { throw UnsupportedOperationException("Factory.create(String) is unsupported. This Factory requires `CreationExtras` to be passed into `create` method.") } public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T = create(modelClass) companion object { @JvmStatic fun from(vararg initializers: ViewModelInitializer<*>): Factory = InitializerViewModelFactory(*initializers) } } // 默认实现 public open class NewInstanceFactory : Factory { @Suppress("DocumentExceptions") override fun <T : ViewModel> create(modelClass: Class<T>): T { return try { modelClass.getDeclaredConstructor().newInstance() } catch (e: NoSuchMethodException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: InstantiationException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: IllegalAccessException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } } public companion object { private var sInstance: NewInstanceFactory? = null @JvmStatic public val instance: NewInstanceFactory @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) get() { if (sInstance == null) { sInstance = NewInstanceFactory() } return sInstance!! } private object ViewModelKeyImpl : Key<String> @JvmField val VIEW_MODEL_KEY: Key<String> = ViewModelKeyImpl } } // 实现的 AndroidViewModel public open class AndroidViewModelFactory private constructor( private val application: Application?, @Suppress("UNUSED_PARAMETER") unused: Int, ) : NewInstanceFactory() { public constructor() : this(null, 0) public constructor(application: Application) : this(application, 0) override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { return if (application != null) { create(modelClass) } else { val application = extras[APPLICATION_KEY] if (application != null) { create(modelClass, application) } else { // For AndroidViewModels, CreationExtras must have an application set if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) { throw IllegalArgumentException( "CreationExtras must have an application by `APPLICATION_KEY`" ) } super.create(modelClass) } } } override fun <T : ViewModel> create(modelClass: Class<T>): T { return if (application == null) { throw UnsupportedOperationException( "AndroidViewModelFactory constructed " + "with empty constructor works only with " + "create(modelClass: Class<T>, extras: CreationExtras)." ) } else { create(modelClass, application) } } private fun <T : ViewModel> create(modelClass: Class<T>, app: Application): T { return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) { try { modelClass.getConstructor(Application::class.java).newInstance(app) } catch (e: NoSuchMethodException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: IllegalAccessException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: InstantiationException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: InvocationTargetException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } } else super.create(modelClass) } public companion object { internal fun defaultFactory(owner: ViewModelStoreOwner): Factory = if (owner is HasDefaultViewModelProviderFactory) owner.defaultViewModelProviderFactory else instance internal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey" private var sInstance: AndroidViewModelFactory? = null @JvmStatic public fun getInstance(application: Application): AndroidViewModelFactory { if (sInstance == null) { sInstance = AndroidViewModelFactory(application) } return sInstance!! } private object ApplicationKeyImpl : Key<Application> @JvmField val APPLICATION_KEY: Key<Application> = ApplicationKeyImpl } } // ComponentActivity 中默认的 Factory class SavedStateViewModelFactory : ViewModelProvider.OnRequeryFactory, ViewModelProvider.Factory { private var application: Application? = null private val factory: ViewModelProvider.Factory // 持有一个AndroidViewModelFactory private var defaultArgs: Bundle? = null private var lifecycle: Lifecycle? = null private var savedStateRegistry: SavedStateRegistry? = null constructor() { factory = ViewModelProvider.AndroidViewModelFactory() } constructor( application: Application?, owner: SavedStateRegistryOwner ) : this(application, owner, null) constructor(application: Application?, owner: SavedStateRegistryOwner, defaultArgs: Bundle?) { savedStateRegistry = owner.savedStateRegistry lifecycle = owner.lifecycle this.defaultArgs = defaultArgs this.application = application factory = if (application != null) getInstance(application) else ViewModelProvider.AndroidViewModelFactory() } override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { val key = extras[ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY] ?: throw IllegalStateException("VIEW_MODEL_KEY must always be provided by ViewModelProvider") return if (extras[SAVED_STATE_REGISTRY_OWNER_KEY] != null && extras[VIEW_MODEL_STORE_OWNER_KEY] != null) { val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] // 拿到 defaultViewModelCreationExtras 中的 application val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass) // 判断需要创建的 ViewModel 是否是AndroidViewModel val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) { findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE) } else { findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE) } // doesn't need SavedStateHandle if (constructor == null) { return factory.create(modelClass, extras) // 直接通过 AndroidViewModel 来创建. } val viewModel = if (isAndroidViewModel && application != null) { newInstance(modelClass, constructor, application, extras.createSavedStateHandle()) } else { newInstance(modelClass, constructor, extras.createSavedStateHandle()) } viewModel } else { val viewModel = if (lifecycle != null) { create(key, modelClass) } else { throw IllegalStateException("SAVED_STATE_REGISTRY_OWNER_KEY and" + "VIEW_MODEL_STORE_OWNER_KEY must be provided in the creation extras to" + "successfully create a ViewModel.") } viewModel } } }
2: ViewModel 和 Activity 如何实现的绑定? 在什么时候销毁?
ComponentActivity 实现了 ViewModelStoreOwner 接口. 提供了可以用来存储 ViewModel 的能力.
在 ViewModel 创建的时候就存在了 Activity 的ViewModelStore 中.
在收到 Activity 的OnDestory 事件的时候就会销毁 ViewModelStore 中所有的 ViewModel.
3: Activity 恢复的时候 ViewModel 是否会恢复? 会恢复什么? SavedStateViewModelFactory 是怎么用的, 存了些什么恢复了些什么? 什么情况下恢复. viewModelStore 中存的 viewModel 既然之后 onDestroy 的时候才会被销毁, 那页面专向会onDestroy吗? 如果会是怎么恢复的, 如果不会,那什么情况下才会被销毁, 什么情况下 SavedStateRegister才能用上.?
!! 由 页面重新旋转导致的页面重绘是不会让ViewModelOwner 存储的 viewModel 清空,因为在 componentActivity 处理 viewModelStore 的清空的时候是有专门判断是否是从 changingConfiguration 来的.
用法:
class xxViewModle(private val application: Application, private val handle: SaveStatehandle):
AndroidViewModel(application){
val query: LiveData<String> = handle.getLiveData("query", "")
fun setQuery(value: String){
handle["query"] = q
}
// 在首次调用 setQuery("123"), 进程异常恢复之后,哪能拿到 query 的监听回调.
}
(1): SavedStateHandle 的存(handle["query"])和取(handle.getLiveData("query", ""))是如何实现?
handle → SaveStateHandle set() 存入的 LiveData/Flow.
进程销毁的时候存 → savedStateProvider 取 regular
初次有值 → SavedStateOwner 调用 SavedStateRegistry performRestore 存入到SavedStateRegistry 内部 restoredState 中, consumeRestoredStateForKey 就可以拿到. 在 SevedStateViewModelFactory create 就已经生成了, 然后通过构造函数的方式传入了 SavedStateHandle.
(2): 为什么可以给构造函数塞入 SaveStatehandle并生效的.
确定 ComponentActivity 使用的是 SavedStateViewModelFactory. SavedStateViewModelFactory 自己内部其实代理了 ApplicationFactory 的 Instance, 在调用他的 create 时候, 先通过 viewModel 的签名判断是否需要 SavedStateHandel 的构造函数, 如果不需要就按照之前的逻辑进行分, 使用 ApplicationFactory 或者 SingleInstanceFactory. 如果需要 SavedStateHandel 则通过 Extras 拿到 SavedStateHandel 对应的参数, LifeCycleOwner, SavedStateRegistryOwner. 这样就把 SavedStateHandle 传入进去了.
(3): 具有存储能力的 SavedStateViewModelFactory 是如何工作的, 哪些场景在会用到 SavedStateViewModelFactory
理论上具有数据恢复能力的位置, componentActivity/ Fragment, 都用到了 SavedStateViewModelFactory
主要是提供了 SaveStatehandle 构造函数,可以用来存储异常删除的数据. 具体的恢复和存入逻辑是由于 SavedStateRigistryOwner提供的. SaveStatehandle 主要实现了(1): 初始的时候拿到数据. (2) 提供了 SavedStateProvider 的存储接口, (3): 将内部数据变为 Flow/ LiveData 的能力.
4: ViewModel 如何实现自定义传参?
-
核心是通过InitializerViewModelFactory实现,InitializerViewModelFactory 的 Create 函数, 会遍历自己的ViewModelInitializer构造函数, 来创建 ViewModel, 而 viewModelFactory 扩展函数, 的参数是一个
InitializerViewModelFactoryBuilder的扩展函数,InitializerViewModelFactoryBuilder中又提供了addInitializer的能力,addInitializer的参数是 类名和创建 ViewModel 的initializer函数,initializer又是CreationExtras的扩展函数,⇒ 最后就形成了这样的形式. 最后也就是自定义 factory , 自定义 extras, 来实现创建过程.
val factory = viewModelFactory { initializer { // CreationExtras 的扩展函数, 可以拿到 key. TestViewModel(this[key]) } }// 定义 key object IdKey: CreateExtras.Key<Int> object NameKey: CreateExtras.key<String> // 定义 ViewModel class TestViewModel(val id: Int, val name: String): ViewModel() // 创建 Factory val factory = viewModelFactory{ initializer{ val id = this[IdKey]?:error("id error.") val name = this[NameKey]?:error("name error.") TestViewModel(id, name) } } // 创建 extras val extras = MutableCreationExtras().apply{ this[IdKey] = 1 this[NameKey] = "Tom" } // 创建 viewModel val viewModel: TestViewModel = factory.create(TestViewModel::class, extras)
5: ViewModel 和 AndroidViewModel 的区别?
两者是否具有 Application. ViewModel 是通过 NewInstanceFactory 来构造的. AndroidViewModel 是通过 AndroidViewModelFactory 来构造的.
6: Activity 的 ViewModel 和 Fragment 的 ViewModel 如何共享?是否可以共享?
ViewModel 存储的位置: ViewModelOwner 的 viewModelStore 中, 提供了 put/get/clean方法. 所以 Activity 和 Fragment 的 viewModel 是否可以共用 取决于使用的是否是同一个 ViewModelOwner的 viewModelStore
Activity → Fragment. Fragment 可以拿到 Activity 的引用, 判断是否是 ViewModelOwner, 如果是的话, 直接通过 构造 ViewModelProvider, 调用 Get 方法就可以拿到.
Fragment → Activity. 通过 FragmentManager 的 findById 的方式拿到 Fragment,然后通过和上面一样的方式来获取
7: Fragment 的 ViewModel 和 Activity ViewModel有和不同?
使用的 ViewModelOwner 不同 → ViewModelStore不同
-
(1) 为什么 ViewModelProvider 需要 ViewModelOwner 作为构造函数,内部只使用了 ViewModelStore
a: 给了 ViewModelOwner 就可以方便的拿到 ViewModelStore
b: 给了 ViewModelOwner 等于给了 Activity 的引用就可以通过 HasDefaultViewModelProviderFactory 借口拿到 ViewModelOwner 制定的 Factory/Extras, Activity/Fragment 都是使用这个逻辑来实现了 SavedStateViewModelFactory.
-
(2) ViewModeStore 还有什么特殊逻辑?
ViewModeStore 只是一个包装的 map, 提供了 set/get/clean 的能力. 但是需要 activity/fragment 在 onDestroy 调用 clean 的时候都会判断是否因为因为配置修改导致的.
-
(3) ViewModel 自己有什么特殊逻辑?
提供了 setTag 和 clean 的逻辑.
8: 常用的 ViewModel 之间的差异? 常用的 Factory 有哪些, 差异是什么?
常用的 ViewModel 只有两个 ViewModel/AndroidViewModel. AndroidViewModel 继承 ViewModel, 差异只是 AndroidViewModel 多了一个构造函数.
常用的 Factory 有: NewInstanceFactory/AndroidViewModelFactory/SavedStateViewModelFactory/InitializerViewModelFactory
-
(1) NewInstanceFactory
用途: 异常情况下的兜底. 只能创建一个空的无参数的构造方法
只实现了参数是类型名称的构造方法. 带 Extras 的都没有实现. 基本很少用.
-
(2) AndroidViewModelFactory
用途: 用来创建一个 application 的 AndroidViewModel. 异常情况下再尝试调用父类创建无参的 ViewModel
注意点: a: 两个 Crate 方法都有实现. b: application 有两个来源, 构造函数可以穿, 通过 Extras 也可以携带.都是通过反射的方式创建的.
-
(3) SavedStateViewModelFactory
用途: ComponentActivity 和 Fragment 的默认 Factory. 实现数据的存储和恢复.
注意点: (a): 如果使用无参数的构造函数, 默认用的就是 AndroidViewModelFactory
(b): 内部会持有一个 factory → AndroidViewModelFactory, 来做具体的创建
(c): 希望传入一个 SavedStateRegistryOwner, 从宿主拿到缓存的数据已经缓存的能力.
(d): ViewModel 的构造函数支持一个额外的参数: SavedStateHandle, 来操作 SavedStateRegistryOwner 中拿到的数据, 已经保存的数据.
(e): SavedStateHandle 提供了恢复的数据转成 LiveDate/StateFlow 的能力, 已经修改的包装.
-
(4) InitializerViewModelFactory
用途: 提供自定义入参的 ViewModel 的实现.
注意点: (a:)InitializerViewFactory中持有一组创建规则, class → CreationExtras.() ⇒ T, 使用符合规则的创建函数来创建 ViewModel.
(b): 创建函数是 CreationExtras.的扩展函数,这样更方便取数.
9: CreationExtras.Key 比 Map<String, Any> 好在哪里?
(1) 基于泛型 → 类型可推导
object IdKey : CreationExtras.Key<Int> val id: Int = extras[IdKey] *// ✅ 编译期保证 Int*
val id = map["id"] as Int map 就做不到.
(2) 避免「字符串命名冲突」
map["id"] = 1 *// A 模块* map["id"] = "xxx" *// B 模块(无感覆盖)*
object UserIdKey : CreationExtras.Key<Int> object OrderIdKey : CreationExtras.Key<Long>
10: 存在哪些好的设计模式?
(1): 创建都通过 ViewModelOwner 来, 让 ViewModel 都和Owner 进行绑定. Owner 同时也是 LifecycleOwner, 这样方便和 Lifecycle 进行关联.
(2): 创建 HasDefaultViewModelProviderFactory接口. 这样就需要把类反复传输, 就可以使用 Owner 自己的 Factory 来实现定制功能.
(3): 结合 SavedStateRegistryOwner 来实现存储能力. 将存储能力够暴露给了 SavedStateHandle 类.
(4): SavedStateHandle 将数据转为 LiveData/Flow, 同时进行了转发, 让使用方可以完全忽略保存和获取的细节.