ViewModel源码解析
源码版本:
* ViewModel:2.8.7
* androidx.activity:activity:1.10.1
* androidx.fragment:fragment:1.8.6
* 更新时间:2025-3月
* 需会使用:Lifecycle
导航:
* Jetpack-Lifecycle源码解析
* Jetpack-LiveData源码解析
* Jetpack-ViewModel源码详解
* 更多的文章看这里:主页
使用
声明ViewModel
class MyViewModel : ViewModel() {
override fun onCleared() {
super.onCleared()
}
}
获取ViewModel
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 获取ViewModel
val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
}
}
viewModels()扩展方法
// Activity
ComponentActivity.viewModels()
// Fragment
Fragment.viewModels()
Fragment.activityViewModels()
Fragment.createViewModelLazy()
增加、获取Closeable
val closeable = object : AutoCloseable {
override fun close() {
// ViewModel销毁时,会自动先通知此回调,后通知ViewModel的onCleared()回调。
}
}
viewModel.addCloseable(closeable) // 增加Closeable
viewModel.addCloseable(key, closeable) // 通过key增加Closeable,如果此key之前已经增加Closeable,他会立即通知之前的那个AutoCloseable关闭。
val myCloseable = viewModel.getCloseable<AutoCloseable>(key) // 通过key获取Closeable
ViewModel生命周期
对应关系
- 从
androidx
的Activity
、Fragment
源码得知:一个androidx
的Activity
、Fragment
对应一个ViewModelStore
。 - 从
ViewModelStore
源码得知:一个ViewModelStore
对应多个ViewModel
。 - 从
ViewModel
源码得知:一个ViewModel
对应多个AutoCloseable
。
总结:一个androidx
的Activity
、Fragment
对应一个ViewModelStore
,一个ViewModelStore
对应多个ViewModel
,一个ViewModel
对应多个AutoCloseable
。
源码
声明ViewModel
ViewModel类
public actual abstract class ViewModel {
private val impl: ViewModelImpl?
public actual constructor() {
impl = ViewModelImpl()
}
public actual constructor(viewModelScope: CoroutineScope) {
impl = ViewModelImpl(viewModelScope)
}
public actual constructor(vararg closeables: AutoCloseable) {
impl = ViewModelImpl(*closeables)
}
public actual constructor(viewModelScope: CoroutineScope, vararg closeables: AutoCloseable) {
impl = ViewModelImpl(viewModelScope, *closeables)
}
@Deprecated(message = "Replaced by `AutoCloseable` overload.", level = DeprecationLevel.HIDDEN)
public constructor(vararg closeables: Closeable) {
impl = ViewModelImpl(*closeables)
}
// 当ViewModel被清除时调用
protected actual open fun onCleared() {}
@MainThread
internal actual fun clear() {
impl?.clear()
// 通知
onCleared()
}
public actual fun addCloseable(key: String, closeable: AutoCloseable) {
impl?.addCloseable(key, closeable)
}
// 添加一个新的Closeable对象,它将在ViewModel.onCleared()被调用之前被直接关闭。
// 如果onCleared()已经被调用,closeable将不会被添加,而是立即被关闭。
public actual open fun addCloseable(closeable: AutoCloseable) {
impl?.addCloseable(closeable)
}
@Deprecated(message = "Replaced by `AutoCloseable` overload.", level = DeprecationLevel.HIDDEN)
public open fun addCloseable(closeable: Closeable) {
impl?.addCloseable(closeable)
}
public actual fun <T : AutoCloseable> getCloseable(key: String): T? = impl?.getCloseable(key)
}
我们接下来,看一下AutoCloseable
接口。
public interface AutoCloseable {
void close() throws Exception;
}
ViewModel
类是一个抽象类,他的所有实现都是由他的实现类ViewModelImpl
实现的,我们来看一下ViewModelImpl
类。
说明:
AutoCloseable
接口,为在ViewModel
销毁时会自动关闭(调用close()
)。ViewModel
构造方法,可以指定CoroutineScope
。ViewModel
构造方法、addCloseable()
、getCloseable()
,可以添加获取AutoCloseable
。
internal class ViewModelImpl {
// 锁
private val lock = SynchronizedObject()
// 有key的AutoCloseable集合,保存与此ViewModel关联的String键和AutoCloseable资源之间的映射。
// 在ViewModel.onCleared()被调用之前,相关的资源将被AutoCloseable.close()。这在ViewModel发布时提供了自动的资源清理。
private val keyToCloseables = mutableMapOf<String, AutoCloseable>()
// 无key的AutoCloseable集合
private val closeables = mutableSetOf<AutoCloseable>()
// 标记是否是已清除
@Volatile
private var isCleared = false
constructor()
constructor(viewModelScope: CoroutineScope) {
// 添加到有key的AutoCloseable集合,并把viewModelScope转为AutoCloseable(会在关闭时,自动取消此传入的viewModelScope)。
addCloseable(VIEW_MODEL_SCOPE_KEY, viewModelScope.asCloseable())
}
constructor(vararg closeables: AutoCloseable) {
// 添加到无key的AutoCloseable集合
this.closeables += closeables
}
constructor(viewModelScope: CoroutineScope, vararg closeables: AutoCloseable) {
// 同时操作上面2个
addCloseable(VIEW_MODEL_SCOPE_KEY, viewModelScope.asCloseable())
this.closeables += closeables
}
@MainThread
fun clear() {
if (isCleared) return // 已经清除,再清除则直接返回。
// 标记已经清除
isCleared = true
// 加锁,保证只能单线程进。
synchronized(lock) {
// 通知关闭keyToCloseables的所有
for (closeable in keyToCloseables.values) {
// 通知此closeable关闭
closeWithRuntimeException(closeable)
}
// 通知关闭closeables的所有
for (closeable in closeables) {
closeWithRuntimeException(closeable)
}
// 只清除没有键的资源,以防止资源的意外重新创建。例如,viewModelScope将被重新创建,从而导致意外行为。
// 清空closeables
closeables.clear()
}
}
// 添加到有key的AutoCloseable集合,方便后续获取。如果此key之前已经有了,他会立即通知之前的那个AutoCloseable立即关闭。
fun addCloseable(key: String, closeable: AutoCloseable) {
// 尽管在用户调用onCleared()之后不应该做任何逻辑操作,但我们确保如果它已经被调用,尝试将添加的closeable立即关闭,以确保不会有泄漏。
if (isCleared) {
// 已经清除,直接通知closeable关闭,并返回。
closeWithRuntimeException(closeable)
return
}
// 添加到有key的AutoCloseable集合,如果此key之前已经有了,他会立即通知之前的那个AutoCloseable立即关闭。
val oldCloseable = synchronized(lock) { keyToCloseables.put(key, closeable) }
closeWithRuntimeException(oldCloseable)
}
// 添加到无key的AutoCloseable集合
fun addCloseable(closeable: AutoCloseable) {
// 同上
if (isCleared) {
closeWithRuntimeException(closeable)
return
}
// 添加到无key的AutoCloseable集合,由于此集合是Set集合,所以相同的closeable再次添加,则不会添加。
synchronized(lock) { closeables += closeable }
}
// 获取此key对应的AutoCloseable,从有key的AutoCloseable集合中获取,如果没有则为空。
fun <T : AutoCloseable> getCloseable(key: String): T? =
@Suppress("UNCHECKED_CAST")
synchronized(lock) { keyToCloseables[key] as T? }
// 通知参数closeable关闭
private fun closeWithRuntimeException(closeable: AutoCloseable?) {
try {
// 通知关闭
closeable?.close()
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
ViewModelImpl
类,是ViewModel
实现类,其内部维护了2个AutoCloseable
集合。
小结
说明:
ViewModel
:为View
层提供数据,可在配置变更后保持相应状态。AutoCloseable
接口:会在ViewModel
销毁时,会自动收到关闭通知(调用close()
)。- 关系:一个
ViewModel
,对应多个AutoCloseable
。CoroutineScope
:ViewModel
构造方法,可以指定CoroutineScope
。AutoCloseable
:ViewModel
构造方法、addCloseable()
、getCloseable()
,可以添加获取AutoCloseable
。ViewModel
的clear()
方法,会先通知所有AutoCloseable
关闭,然后再通知ViewModel
的onCleared()
回调。
获取ViewModel
,是通过ViewModelProvider(this).get(MyViewModel::class.java)
获取的,我们先来看ViewModelProvider
的创建,然后再来看其get()
方法获取。
创建ViewModelProvider
new创建
public actual open class ViewModelProvider private constructor(
private val impl: ViewModelProviderImpl,
) {
// 以下两个构造方法,都是调用的此构造方法,而此构造方法又是调用的上面的主构造方法。
@JvmOverloads
public constructor(
store: ViewModelStore,
factory: Factory,
defaultCreationExtras: CreationExtras = CreationExtras.Empty,
) : this(ViewModelProviderImpl(store, factory, defaultCreationExtras))
public constructor(
owner: ViewModelStoreOwner,
) : this(
store = owner.viewModelStore,
factory = ViewModelProviders.getDefaultFactory(owner),
defaultCreationExtras = ViewModelProviders.getDefaultCreationExtras(owner)
)
public constructor(
owner: ViewModelStoreOwner,
factory: Factory,
) : this(
store = owner.viewModelStore,
factory = factory,
defaultCreationExtras = ViewModelProviders.getDefaultCreationExtras(owner)
)
}
ViewModelProvider
类的创建,需要创建ViewModelProviderImpl
类,而ViewModelProviderImpl
类的创建需要ViewModelStore
、ViewModelProvider.Factory
、CreationExtras
。
说明:
ViewModelProviderImpl
:他是ViewModelProvider
的具体实现,其内部的get()
方法就是调用的此,详细看后面的-获取ViewModel。ViewModelStore
:可以从ViewModelStoreOwner
中获取。ViewModelProvider.Factory
:未指定,则默认为ViewModelProviders.getDefaultFactory(owner)
。CreationExtras
:未指定,则默认为ViewModelProviders.getDefaultCreationExtras(owner)
。
create创建
public actual companion object {
@JvmStatic
@Suppress("MissingJvmstatic")
public actual fun create(
owner: ViewModelStoreOwner,
factory: Factory,
extras: CreationExtras,
): ViewModelProvider = ViewModelProvider(owner.viewModelStore, factory, extras)
@JvmStatic
@Suppress("MissingJvmstatic")
public actual fun create(
store: ViewModelStore,
factory: Factory,
extras: CreationExtras
): ViewModelProvider = ViewModelProvider(store, factory, extras)
@JvmField
public actual val VIEW_MODEL_KEY: Key<String> = ViewModelProviders.ViewModelKey
}
ViewModelProvider.create()
方法,内部调用上面的3参的构造方法。
小结
说明:
ViewModelProvider
:ViewModel
提供者,用于获取ViewModel
(内部如果没有,则会创建ViewModel
并保存,详细看后面:获取ViewModel)。ViewModelProvider
的创建,分为2种,new创建、create创建(viewModels()
扩展方法用的是此,详细看后面:viewModels()扩展方法)。ViewModelProvider
类的创建,其内部核心类:
ViewModelStore
:ViewModel
商店,用来存储或获取ViewModel
,详细看后面:获取ViewModelStore。Factory
:ViewModel
的创建工厂,用来创建ViewModel
实例,详细看后面:获取Factory。CreationExtras
:为Factory
创建ViewModel
提供额外信息,详细看后面:获取CreationExtras。
我们依次看一下创建ViewModelProvider
需要的核心类(ViewModelStore
、ViewModelProvider.Factory
、CreationExtras
)他们是如果获取的,最后再来看一下ViewModelProvider
的get()
方法。
获取ViewModelStore
ViewModelStore
ViewModelStore类
public open class ViewModelStore {
// ViewModel集合
private val map = mutableMapOf<String, ViewModel>()
// 保存ViewModel,如果key已经存在,则值进行覆盖,之前的ViewModel则调用clear()清空逻辑。
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public fun put(key: String, viewModel: ViewModel) {
val oldViewModel = map.put(key, viewModel)
oldViewModel?.clear()
}
// 获取ViewModel,如果没有则为null。
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public operator fun get(key: String): ViewModel? {
return map[key]
}
// 获取所有的key
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public fun keys(): Set<String> {
return HashSet(map.keys)
}
// 通知所有ViewModel的clear()(清空),并清除其内部ViewModel集合。
public fun clear() {
for (vm in map.values) {
vm.clear()
}
map.clear()
}
}
ViewModelStore
为ViewModel
商店,它是用来存储或获取ViewModel
的,是使用LinkedHashMap
来实现的。其clear()
方法会通知所有ViewModel
的clear()
(清空),并清除其内部ViewModel
集合。
默认ViewModelStore
在创建ViewModelProvider
类时,ViewModelStore
是可以从ViewModelStoreOwner
中获取的,我们接下来看一下他的实现。
ViewModelStoreOwner类
public interface ViewModelStoreOwner {
public val viewModelStore: ViewModelStore
}
ViewModelStoreOwner
为ViewModelStore
的持有者,通过它的子类可以获取到ViewModelStore
。
androidx
的Activity
和Fragment
都已经实现了ViewModelStoreOwner
,我们分别看一下具体实现。
Activity
androidx.activity.ComponentActivity类
open class ComponentActivity() :
androidx.core.app.ComponentActivity(),
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
OnUserLeaveHintProvider,
MenuHost,
FullyDrawnReporterOwner {
private var _viewModelStore: ViewModelStore? = null
override val viewModelStore: ViewModelStore
get() {
// 不能在onCreate调用之前获取ViewModel
checkNotNull(application) {
("Your activity is not yet attached to the " +
"Application instance. You can't request ViewModel before onCreate call.")
}
// 确保ViewModelStore
ensureViewModelStore()
// 返回ViewModelStore
return _viewModelStore!!
}
private fun ensureViewModelStore() {
if (_viewModelStore == null) {
val nc = lastNonConfigurationInstance as NonConfigurationInstances?
if (nc != null) {
// 从 NonConfigurationInstances 中恢复ViewModelStore
_viewModelStore = nc.viewModelStore
}
if (_viewModelStore == null) {
// _viewModelStore为空,则创建。
_viewModelStore = ViewModelStore()
}
}
}
androidx
Activity
实现了ViewModelStoreOwner
,获取ViewModelStore
,先从 NonConfigurationInstances
中恢复ViewModelStore
(确保Activity
重建后还能获取到之前的ViewModelStore
,具体分析看下面-ViewModel是如何保持不变的?),如果还是没有,则进行创建。
说明:
- 一个
androidx
Activity
,对应一个ViewModelStore
。androidx
Activity
不能在onCreate
调用之前获取ViewModel
。
Fragment
androidx.fragment.app.Fragment类
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
ActivityResultCaller {
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mFragmentManager == null) {
// 不能从detached的Fragment访问ViewModels
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
if (getMinimumMaxLifecycleState() == Lifecycle.State.INITIALIZED.ordinal()) {
// 当使用setMaxLifecycle(INITIALIZED)时,不支持在Fragment到达onCreate()之前调用getViewModelStore()
throw new IllegalStateException("Calling getViewModelStore() before a Fragment "
+ "reaches onCreate() when using setMaxLifecycle(INITIALIZED) is not "
+ "supported");
}
return mFragmentManager.getViewModelStore(this);
}
}
FragmentManager –> getViewModelStore方法
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
// mNonConfig为FragmentManagerViewModel
return mNonConfig.getViewModelStore(f);
}
FragmentManagerViewModel –> getViewModelStore方法
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
androidx
Fragment
实现了ViewModelStoreOwner
,获取ViewModelStore
,先从 FragmentManagerViewModel
中恢复ViewModelStore
(确保Fragment
重建后还能获取到之前的ViewModelStore
,具体分析看下面-ViewModel是如何保持不变的?),如果还是没有,则进行创建。
说明:
- 一个
androidx
Fragment
,对应一个ViewModelStore
。androidx
Fragment
不能在onDetach
调用之后获取ViewModel
。
小结
说明:
ViewModelStore
:ViewModel
的商店,它是用来存储或获取ViewModel
的,是使用LinkedHashMap
来实现的。其clear()
方法会先通知所有ViewModel
的clear()
(ViewModel
的clear()
:先清空所有AutoCloseable
,后通知此ViewModel
的onCleared()
回调),后清空其内部ViewModel
集合。ViewModelStoreOwner
:ViewModelStore
的持有者,通过它的子类可以获取到ViewModelStore
,androidx
的Activity
、Fragment
都已经实现了ViewModelStoreOwner
。- 关系:
- 从
androidx
的Activity
、Fragment
源码得知:一个androidx
的Activity
、Fragment
对应一个ViewModelStore
。- 从
ViewModelStore
源码得知:一个ViewModelStore
对应多个ViewModel
。- 从
ViewModel
源码得知:一个ViewModel
对应多个AutoCloseable
。- 总结:一个
androidx
的Activity
、Fragment
对应一个ViewModelStore
,一个ViewModelStore
对应多个ViewModel
,一个ViewModel
对应多个AutoCloseable
。
获取Factory
Factory
ViewModelProvider.Factory类
public actual interface Factory {
// 创建给定ViewModel Class的新实例,默认实现抛出UnsupportedOperationException异常。
public fun <T : ViewModel> create(modelClass: Class<T>): T =
ViewModelProviders.unsupportedCreateViewModel()
// 创建给定ViewModel Class的新实例。
public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
create(modelClass)
// 调用的上面的
public actual fun <T : ViewModel> create(
modelClass: KClass<T>,
extras: CreationExtras,
): T = create(modelClass.java, extras)
public companion object {
@JvmStatic
public fun from(vararg initializers: ViewModelInitializer<*>): Factory =
ViewModelProviders.createInitializerFactory(*initializers)
}
}
ViewModelProvider.Factory
为ViewModel
的创建工厂,此Factory
通过ViewModel
类的class
,创建ViewModel
实例。我们分别来看一下它的子类NewInstanceFactory
、AndroidViewModelFactory
。
NewInstanceFactory
ViewModelProvider.NewInstanceFactory类
public open class NewInstanceFactory
@Suppress("SingletonConstructor")
constructor() : Factory {
// 以下2个构造方法,全部都是调用的此,此JvmViewModelProviders用的反射创建。
public override fun <T : ViewModel> create(modelClass: Class<T>): T =
JvmViewModelProviders.createViewModel(modelClass)
public override fun <T : ViewModel> create(
modelClass: Class<T>,
extras: CreationExtras,
): T = create(modelClass)
public override fun <T : ViewModel> create(
modelClass: KClass<T>,
extras: CreationExtras,
): T = create(modelClass.java, extras)
public companion object {
private var _instance: NewInstanceFactory? = null
// 单例 NewInstanceFactory
@JvmStatic
public val instance: NewInstanceFactory
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
get() {
if (_instance == null) {
_instance = NewInstanceFactory()
}
return _instance!!
}
@JvmField
public val VIEW_MODEL_KEY: Key<String> = ViewModelProviders.ViewModelKey
}
}
internal object JvmViewModelProviders {
@Suppress("DocumentExceptions")
fun <T : ViewModel> createViewModel(modelClass: Class<T>): T =
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)
}
}
NewInstanceFactory
类,继承Factory
,实现了create()
方法,通过ViewModel
类的class
,反射创建无参ViewModel
实例。
说明:
- 使用
NewInstanceFactory
创建,此ViewModel
必须有,无参的且不是私有的构造方法。
- 可以处理如下
ViewModel
:
class MyViewModel : ViewModel()
,由NewInstanceFactory
创建。
NewInstanceFactory.instance
为全局单例NewInstanceFactory
,防止了每次创建工厂,优化了性能。
AndroidViewModelFactory
ViewModelProvider.AndroidViewModelFactory类
public open class AndroidViewModelFactory
private constructor(
private val application: Application?,
// 无用参数
@Suppress("UNUSED_PARAMETER") unused: Int,
) : NewInstanceFactory() {
@Suppress("SingletonConstructor")
public constructor() : this(application = null, unused = 0)
// 一般都是通过此创建
@Suppress("SingletonConstructor")
public constructor(application: Application) : this(application, unused = 0)
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
return if (application != null) {
// application不为空,调用下面的create(modelClass)方法创建。
create(modelClass)
} else {
// application为空,从扩展中继续获取。
val application = extras[APPLICATION_KEY]
if (application != null) {
// application不为空,直接调用下面的create(modelClass, application)方法创建。
create(modelClass, application)
} else {
// application为空
if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
// 是AndroidViewModel子类,必须有application,抛出异常。
throw IllegalArgumentException(
"CreationExtras must have an application by `APPLICATION_KEY`"
)
}
// application为空,并且不是AndroidViewModel子类,调用父类的create()(反射创建无参ViewModel)。
super.create(modelClass)
}
}
}
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return if (application == null) {
// application为空,抛出异常AndroidViewModelFactory空构造函数,必须用上面的create(modelClass,extras)方法创建。
throw UnsupportedOperationException(
"AndroidViewModelFactory constructed " +
"with empty constructor works only with " +
"create(modelClass: Class<T>, extras: CreationExtras)."
)
} else {
// application不为空,调用下面的create(modelClass, application)方法创建。
create(modelClass, application)
}
}
@Suppress("DocumentExceptions")
private fun <T : ViewModel> create(modelClass: Class<T>, app: Application): T {
return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
try {
// 此ViewModel为AndroidViewModel的子类,则传入Application并创建。
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 {
private var _instance: AndroidViewModelFactory? = null
// 单例 AndroidViewModelFactory
@JvmStatic
public fun getInstance(application: Application): AndroidViewModelFactory {
if (_instance == null) {
_instance = AndroidViewModelFactory(application)
}
return _instance!!
}
@JvmField
public val APPLICATION_KEY: Key<Application> = object : Key<Application> {}
}
}
AndroidViewModelFactory
类,继承NewInstanceFactory
,重写了create()
方法,通过ViewModel
类的class
判断,如果此ViewModel
为AndroidViewModel
的子类,则传入Application
并反射创建;否则为普通ViewModel
走父类NewInstanceFactory
的创建(反射创建无参ViewModel
实例)。
说明:
- 使用
AndroidViewModelFactory
创建,如果此ViewModel
是AndroidViewModel
子类,必须有一参的且是Application
且不是私有的构造方法(不能无参);否则为普通ViewModel
,必须有无参的且不是私有的构造方法(不能有参)。
- 可以处理如下
ViewModel
:
class MyViewModel : ViewModel()
,由NewInstanceFactory
创建。
class MyViewModel(application: Application) : AndroidViewModel(application)
,由AndroidViewModelFactory
创建。
AndroidViewModelFactory.getInstance(application)
为全局单例AndroidViewModelFactory
,防止了每次创建工厂,优化了性能。
默认Factory
在创建ViewModelProvider
类时,如果ViewModelProvider.Factory
未指定,则默认为ViewModelProviders.getDefaultFactory(owner)
,我们接下来看一下他的实现。
internal fun getDefaultFactory(owner: ViewModelStoreOwner): ViewModelProvider.Factory =
if (owner is HasDefaultViewModelProviderFactory) {
owner.defaultViewModelProviderFactory
} else {
DefaultViewModelProviderFactory
}
ViewModelProviders.getDefaultFactory(owner)
方法,如果owner
实现HasDefaultViewModelProviderFactory
接口,则获取其提供的Factory
,否则使用DefaultViewModelProviderFactory
。
我们先来看一下DefaultViewModelProviderFactory
类,然后再来看一下HasDefaultViewModelProviderFactory
接口。
internal actual object DefaultViewModelProviderFactory : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: KClass<T>, extras: CreationExtras): T =
// 反射创建无参ViewModel
JvmViewModelProviders.createViewModel(modelClass.java)
}
DefaultViewModelProviderFactory
,内部是使用反射创建无参ViewModel
,详细看上面-JvmViewModelProviders类源码。
HasDefaultViewModelProviderFactory类
public interface HasDefaultViewModelProviderFactory {
// 默认Factory
public val defaultViewModelProviderFactory: ViewModelProvider.Factory
// 默认CreationExtras
public val defaultViewModelCreationExtras: CreationExtras
get() = CreationExtras.Empty
}
HasDefaultViewModelProviderFactory
接口,为标记是否可以获取到默认Factory
、默认CreationExtras
(详细见下面-获取CreationExtras)。
androidx
的Activity
和Fragment
都已经实现了HasDefaultViewModelProviderFactory
,我们来分别看一下它们的defaultViewModelProviderFactory
具体实现。
Activity
androidx.activity.ComponentActivity类
open class ComponentActivity() :
androidx.core.app.ComponentActivity(),
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
OnUserLeaveHintProvider,
MenuHost,
FullyDrawnReporterOwner {
override val defaultViewModelProviderFactory: ViewModelProvider.Factory by lazy {
// 创建SavedStateViewModelFactory,会把Application、当前页面传入的参数,传入到构造方法中。
SavedStateViewModelFactory(application, this, if (intent != null) intent.extras else null)
}
}
androidx
的Activity
,getDefaultViewModelProviderFactory()
是使用lazy()
方法,只让其创建一次。
Fragment
androidx.fragment.app.Fragment类
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
ActivityResultCaller {
ViewModelProvider.Factory mDefaultFactory;
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mFragmentManager == null) {
// 不能从detached的Fragment访问ViewModels
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
if (mDefaultFactory == null) {
// 默认工厂为空,则进行创建SavedStateViewModelFactory。
Application application = null;
Context appContext = requireContext().getApplicationContext();
while (appContext instanceof ContextWrapper) {
if (appContext instanceof Application) {
application = (Application) appContext;
break;
}
appContext = ((ContextWrapper) appContext).getBaseContext();
}
if (application == null && FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(FragmentManager.TAG, "Could not find Application instance from "
+ "Context " + requireContext().getApplicationContext() + ", you will "
+ "not be able to use AndroidViewModel with the default "
+ "ViewModelProvider.Factory");
}
// 创建SavedStateViewModelFactory,会把Application、当前页面传入的参数,传入到构造方法中。
mDefaultFactory = new SavedStateViewModelFactory(
application,
this,
getArguments());
}
return mDefaultFactory;
}
}
androidx
的Fragment
,getDefaultViewModelProviderFactory()
方法,会判断如果没有创建会直接创建,否则直接返回,只让其创建一次。
androidx
的Activity
和Fragment
的getDefaultViewModelProviderFactory()
实现相同,都是创建SavedStateViewModelFactory
并会把Application
、当前页面传入的参数,传入到构造方法中。
我们接下来,看一下SavedStateViewModelFactory
类。
SavedStateViewModelFactory类
class SavedStateViewModelFactory : ViewModelProvider.OnRequeryFactory, ViewModelProvider.Factory {
private var application: Application? = null
private val factory: ViewModelProvider.Factory
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)
// 构造方法,有传默认参数。Activity、Fragment内的SavedStateViewModelFactory创建,就是调用的此。
@SuppressLint("LambdaLast")
constructor(application: Application?, owner: SavedStateRegistryOwner, defaultArgs: Bundle?) {
savedStateRegistry = owner.savedStateRegistry
lifecycle = owner.lifecycle
this.defaultArgs = defaultArgs
this.application = application
// 工厂,如果application为空,则用全局的单例的AndroidViewModelFactory(有application);
// 否则就新建一个AndroidViewModelFactory(无application)。
factory = if (application != null) getInstance(application)
else ViewModelProvider.AndroidViewModelFactory()
}
// 通过ViewModelProvider(this).get()创建ViewModel,就是调用的此方法,详细看后面:获取ViewModel。
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
// 当前ViewModel的key
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) { // 通常会走这个逻辑
// 有SavedStateRegistryOwner、ViewModelStateRegistryOwner,用于extras.createSavedStateHandle()创建SavedStateHandle用。
// 获取Application
val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]
// 是否是AndroidViewModel子类
val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
// 是AndroidViewModel子类,并且application不为空,获取(Application, SavedStateHandle)签名的构造方法。
findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
} else {
// 不是AndroidViewModel子类,或者application为空,获取(SavedStateHandle)签名的构造方法。
findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
}
if (constructor == null) {
// 没有获取到,则说明是没用SavedStateHandle的构造方法,则直接用factory(AndroidViewModelFactory)处理。
return factory.create(modelClass, extras)
}
// 以下为需要SavedStateHandle
val viewModel = if (isAndroidViewModel && application != null) {
// 反射创建(Application, SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
newInstance(modelClass, constructor, application, extras.createSavedStateHandle())
} else {
// 反射创建(SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
newInstance(modelClass, constructor, extras.createSavedStateHandle())
}
// 返回ViewModel
viewModel
} else {
// 没有SavedStateRegistryOwner、ViewModelStateRegistryOwner
val viewModel = if (lifecycle != null) {
// lifecycle不为空,直接调用下面的create(key, modelClass)方法。
create(key, modelClass)
} else {
// lifecycle为空,必须提供savedStateRegistryOwner、viewModelStateRegistryOwner。
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
viewModel
}
}
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
// 使用空构造函数构造的SavedStateViewModelFactory,只支持调用create(modelClass, extras)。
val lifecycle = lifecycle
?: throw UnsupportedOperationException(
"SavedStateViewModelFactory constructed with empty constructor supports only " +
"calls to create(modelClass: Class<T>, extras: CreationExtras)."
)
// 是否是AndroidViewModel子类
val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
// 是AndroidViewModel子类,并且application不为空,获取(Application, SavedStateHandle)签名的构造方法。
findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
} else {
// 不是AndroidViewModel子类,或者application为空,获取(SavedStateHandle)签名的构造方法。
findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
}
// 没有获取到,则说明是没用SavedStateHandle的构造方法,则直接用AndroidViewModelFactory或NewInstanceFactory处理,并返回。
constructor
?:
return if (application != null) factory.create(modelClass)
else instance.create(modelClass)
// 以下为需要SavedStateHandle
// 获取LegacySavedStateHandleController创建的控制器
val controller = LegacySavedStateHandleController.create(
savedStateRegistry!!, lifecycle, key, defaultArgs
)
val viewModel: T = if (isAndroidViewModel && application != null) {
// 反射创建(Application, SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
newInstance(modelClass, constructor, application!!, controller.handle)
} else {
// 反射创建(SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
newInstance(modelClass, constructor, controller.handle)
}
// 让controller在viewModel关闭时,关闭。
viewModel.addCloseable(
LegacySavedStateHandleController.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller
)
// 返回ViewModel
return viewModel
}
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
// 使用类名作为key,创建ViewModel。
return create(canonicalName, modelClass)
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
override fun onRequery(viewModel: ViewModel) {
// needed only for legacy path
if (lifecycle != null) {
LegacySavedStateHandleController.attachHandleIfNeeded(
viewModel,
savedStateRegistry!!,
lifecycle!!
)
}
}
}
internal fun <T : ViewModel?> newInstance(
modelClass: Class<T>,
constructor: Constructor<T>,
vararg params: Any
): T {
return try {
// 反射创建
constructor.newInstance(*params)
} catch (e: IllegalAccessException) {
throw RuntimeException("Failed to access $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("A $modelClass cannot be instantiated.", e)
} catch (e: InvocationTargetException) {
throw RuntimeException(
"An exception happened in constructor of $modelClass", e.cause
)
}
}
// (Application, SavedStateHandle)签名
private val ANDROID_VIEWMODEL_SIGNATURE = listOf<Class<*>>(
Application::class.java,
SavedStateHandle::class.java
)
// (SavedStateHandle)签名
private val VIEWMODEL_SIGNATURE = listOf<Class<*>>(SavedStateHandle::class.java)
// 找到对应签名的构造方法
internal fun <T> findMatchingConstructor(
modelClass: Class<T>,
signature: List<Class<*>>
): Constructor<T>? {
for (constructor in modelClass.constructors) {
val parameterTypes = constructor.parameterTypes.toList()
if (signature == parameterTypes) {
@Suppress("UNCHECKED_CAST")
return constructor as Constructor<T>
}
if (signature.size == parameterTypes.size && parameterTypes.containsAll(signature)) {
throw UnsupportedOperationException(
"Class ${modelClass.simpleName} must have parameters in the proper " +
"order: $signature"
)
}
}
return null
}
SavedStateViewModelFactory
类,继承Factory
,重写了create()
方法,通过ViewModel
类的class
判断,如果此ViewModel
有使用SavedStateHandle
,则传入SavedStateHandle
并反射创建;否则为普通ViewModel
、AndroidViewModel
子类,走factoryAndroidViewModelFactory
的创建(详细见上面)。
说明:
- 使用
SavedStateViewModelFactory
创建,如果此ViewModel
构造方法里面没有用SavedStateHandle
,则直接使用AndroidViewModelFactory
创建;否则,则反射创建(Application, SavedStateHandle)
或(SavedStateHandle)
签名的构造方法。
- 可以处理如下
ViewModel
:
class MyViewModel : ViewModel()
,由NewInstanceFactory
创建。class MyViewModel(application: Application) : AndroidViewModel(application)
,由AndroidViewModelFactory
创建。
class MyViewModel(val handle: SavedStateHandle) : ViewModel()
,由SavedStateViewModelFactory
创建。
class MyViewModel(application: Application, val handle: SavedStateHandle) : AndroidViewModel(application)
,由SavedStateViewModelFactory
创建。
- 由于
androidx
的Activity
和Fragment
,都实现了获取默认Factory
,都是创建SavedStateViewModelFactory
(只让其创建一次)并会把Application
、当前页面传入的参数,传入到构造方法中。- 由于
SavedStateHandle
的创建,传入了当前页面传入的参数,所以通过SavedStateHandle
也能获取到当前页面传入的参数。
小结
说明:
ViewModelProvider.Factory
:ViewModel
的创建工厂,此Factory
通过ViewModel
类的class
,创建ViewModel
实例。HasDefaultViewModelProviderFactory
:是否有默认Factory
,通过它的子类可以获取到默认Factory
、默认CreationExtras
(详细见下面-获取CreationExtras),androidx
的Activity
、Fragment
都已经实现了HasDefaultViewModelProviderFactory
。androidx
的Activity
、Fragment
实现HasDefaultViewModelProviderFactory
,其getDefaultViewModelProviderFactory()
方法分别维护了一个SavedStateViewModelFactory
(只让其创建一次)。SavedStateViewModelFactory
类,支持创建,有Application
、有SavedStateHandle
、两者都有、两者都没有的ViewModel
,详细见上面-说明。
- 可以处理如下
ViewModel
:class MyViewModel : ViewModel()
,由NewInstanceFactory
创建。class MyViewModel(application: Application) : AndroidViewModel(application)
,由AndroidViewModelFactory
创建。class MyViewModel(val handle: SavedStateHandle) : ViewModel()
,由SavedStateViewModelFactory
创建。class MyViewModel(application: Application, val handle: SavedStateHandle) : AndroidViewModel(application)
,由SavedStateViewModelFactory
创建。- 关系:一个
androidx
的Activity
、Fragment
,对应一个SavedStateViewModelFactory
。
获取CreationExtras
CreationExtras
CreationExtras类
public abstract class CreationExtras internal constructor() {
// 存储的数据集合,key为Key,值为Any。
internal val map: MutableMap<Key<*>, Any?> = mutableMapOf()
// CreationExtras元素的键。
public interface Key<T>
// 通过key获取相关联的元素
public abstract operator fun <T> get(key: Key<T>): T?
// CreationExtras-空实现
public object Empty : CreationExtras() {
override fun <T> get(key: Key<T>): T? = null
}
}
// CreationExtras-可修改
// initialExtras:为初始化值,默认为空。
public class MutableCreationExtras(initialExtras: CreationExtras = Empty) : CreationExtras() {
init {
map.putAll(initialExtras.map)
}
// 设置
public operator fun <T> set(key: Key<T>, t: T) {
map[key] = t
}
// 获取
public override fun <T> get(key: Key<T>): T? {
@Suppress("UNCHECKED_CAST")
return map[key] as T?
}
}
CreationExtras
,为传入Factory
的create()
方法的简单对象(类似map
),为工厂创建ViewModel
提供额外信息。它允许使Factory
实现无状态,这使得工厂注入更容易,因为不需要在构建时提供所有信息。
说明:
CreationExtras
有两个实现类,Empty
(空)、MutableCreationExtras
(可修改)。
默认CreationExtras
在创建ViewModelProvider
类时,如果CreationExtras
未指定,则默认为ViewModelProviders.getDefaultCreationExtras(owner)
,我们接下来看一下他的实现。
internal fun getDefaultCreationExtras(owner: ViewModelStoreOwner): CreationExtras =
if (owner is HasDefaultViewModelProviderFactory) {
owner.defaultViewModelCreationExtras
} else {
CreationExtras.Empty
}
ViewModelProviders.getDefaultCreationExtras(owner)
方法,如果owner
实现HasDefaultViewModelProviderFactory
接口,则获取其提供的CreationExtras
,否则使用CreationExtras.Empty
(空)。
HasDefaultViewModelProviderFactory类
public interface HasDefaultViewModelProviderFactory {
// 默认Factory
public val defaultViewModelProviderFactory: ViewModelProvider.Factory
// 默认CreationExtras
public val defaultViewModelCreationExtras: CreationExtras
get() = CreationExtras.Empty
}
HasDefaultViewModelProviderFactory
接口,为标记是否可以获取到默认Factory
(详细见上面-获取Factory)、默认CreationExtras
。
androidx
的Activity
和Fragment
都已经实现了HasDefaultViewModelProviderFactory
,我们来分别看一下它们的defaultViewModelCreationExtras
具体实现。
Activity
androidx.activity.ComponentActivity类
open class ComponentActivity() :
androidx.core.app.ComponentActivity(),
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
OnUserLeaveHintProvider,
MenuHost,
FullyDrawnReporterOwner {
@get:CallSuper
override val defaultViewModelCreationExtras: CreationExtras
get() {
// 创建CreationExtras
val extras = MutableCreationExtras()
if (application != null) {
// 存入Application
extras[APPLICATION_KEY] = application
}
// 存入SavedStateRegistryOwner
extras[SAVED_STATE_REGISTRY_OWNER_KEY] = this
// 存入ViewModelStoreOwner
extras[VIEW_MODEL_STORE_OWNER_KEY] = this
val intentExtras = intent?.extras
if (intentExtras != null) {
// 存入参数
extras[DEFAULT_ARGS_KEY] = intentExtras
}
return extras
}
}
Fragment
androidx.fragment.app.Fragment类
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
ViewModelStoreOwner, HasDefaultViewModelProviderFactory, SavedStateRegistryOwner,
ActivityResultCaller {
ViewModelProvider.Factory mDefaultFactory;
@NonNull
@Override
@CallSuper
public CreationExtras getDefaultViewModelCreationExtras() {
Application application = null;
Context appContext = requireContext().getApplicationContext();
while (appContext instanceof ContextWrapper) {
if (appContext instanceof Application) {
application = (Application) appContext;
break;
}
appContext = ((ContextWrapper) appContext).getBaseContext();
}
if (application == null && FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(FragmentManager.TAG, "Could not find Application instance from "
+ "Context " + requireContext().getApplicationContext() + ", you will "
+ "not be able to use AndroidViewModel with the default "
+ "ViewModelProvider.Factory");
}
// 创建CreationExtras
MutableCreationExtras extras = new MutableCreationExtras();
if (application != null) {
// 存入Application
extras.set(ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY, application);
}
// 存入SavedStateRegistryOwner
extras.set(SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY, this);
// 存入ViewModelStoreOwner
extras.set(SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY, this);
if (getArguments() != null) {
// 存入参数
extras.set(SavedStateHandleSupport.DEFAULT_ARGS_KEY, getArguments());
}
return extras;
}
}
androidx
的Activity
和Fragment
的getDefaultViewModelCreationExtras()
实现相同,都是每次创建新的MutableCreationExtras
并存入Application
、SavedStateRegistryOwner
、ViewModelStoreOwner
、当前页面传入的参数,以方便后续create()
时使用。
小结
说明:
CreationExtras
:传入Factory
的create()
方法的简单对象(类似map
),为工厂创建ViewModel
提供额外信息。它允许使Factory
实现无状态,这使得工厂注入更容易,因为不需要在构建时提供所有信息。HasDefaultViewModelProviderFactory
:是否有默认Factory
,通过它的子类可以获取到默认Factory
(详细见上面-获取Factory)、默认CreationExtras
,androidx
的Activity
、Fragment
都已经实现了HasDefaultViewModelProviderFactory
。androidx
的Activity
、Fragment
实现HasDefaultViewModelProviderFactory
,其getDefaultViewModelCreationExtras()
方法每次创建新的MutableCreationExtras
并返回(创建会存入Application
、SavedStateRegistryOwner
、ViewModelStoreOwner
、当前页面传入的参数,以方便后续create()
时使用)。
获取ViewModel
ViewModelProvider–> get方法
@MainThread
public actual operator fun <T : ViewModel> get(modelClass: KClass<T>): T =
impl.getViewModel(modelClass)
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T =
// 调用的是上面get(modelClass: KClass<T>)
get(modelClass.kotlin)
@MainThread
public actual operator fun <T : ViewModel> get(key: String, modelClass: KClass<T>): T =
impl.getViewModel(modelClass, key)
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T =
impl.getViewModel(modelClass.kotlin, key)
ViewModelProvider
的get()
方法,支持通过Java
的Class
、Kotlin
的KClass
、指定key
,获取对应的ViewModel
,他的具体实现是通过ViewModelProviderImpl
类的getViewModel()
方法实现的,我们一起来看一下。
internal class ViewModelProviderImpl(
private val store: ViewModelStore,
private val factory: ViewModelProvider.Factory,
private val extras: CreationExtras,
) {
constructor(
owner: ViewModelStoreOwner,
factory: ViewModelProvider.Factory,
extras: CreationExtras,
) : this(owner.viewModelStore, factory, extras)
@Suppress("UNCHECKED_CAST")
internal fun <T : ViewModel> getViewModel(
modelClass: KClass<T>,
// key,默认为:androidx.lifecycle.ViewModelProvider.DefaultKey:全路径类名。
key: String = ViewModelProviders.getDefaultKey(modelClass),
): T {
// 从ViewModelStore中获取
val viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
// viewModel不为空,并且是目标类modelClass的实例,则直接返回。
if (factory is ViewModelProvider.OnRequeryFactory) {
factory.onRequery(viewModel!!)
}
// 返回找到的viewModel
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody") if (viewModel != null) {
// TODO: log a warning.
}
}
// 以下为,没有找到ViewModel,则直接创建,并存入到ViewModelStore中。
// 创建CreationExtras,并把之前的extras存入。
val extras = MutableCreationExtras(extras)
// 存入key
extras[ViewModelProviders.ViewModelKey] = key
// 返回创建的viewModel,并将其添加到ViewModelStore中。
return createViewModel(factory, modelClass, extras).also { vm -> store.put(key, vm) }
}
}
内部通过ViewModelProviders.getDefaultKey(modelClass)
获取默认key
,通过createViewModel(factory, modelClass, extras)
创建ViewModel
,我们一起来看一下。
internal object ViewModelProviders {
private const val VIEW_MODEL_PROVIDER_DEFAULT_KEY: String =
"androidx.lifecycle.ViewModelProvider.DefaultKey"
// 获取默认key
internal fun <T : ViewModel> getDefaultKey(modelClass: KClass<T>): String {
val canonicalName = requireNotNull(modelClass.canonicalName) {
"Local and anonymous classes can not be ViewModels"
}
// androidx.lifecycle.ViewModelProvider.DefaultKey:全路径类名
return "$VIEW_MODEL_PROVIDER_DEFAULT_KEY:$canonicalName"
}
}
internal actual fun <VM : ViewModel> createViewModel(
factory: ViewModelProvider.Factory,
modelClass: KClass<VM>,
extras: CreationExtras
): VM {
return try {
// 通过ViewModelProvider.Factory的create(modelClass, extras)方法创建
factory.create(modelClass, extras)
} catch (e: AbstractMethodError) {
try {
factory.create(modelClass.java, extras)
} catch (e: AbstractMethodError) {
factory.create(modelClass.java)
}
}
}
ViewModelProviderImpl
的getViewModel(modelClass,key)
方法,会先从ViewModelStore
中获取ViewModel
,如果有并且是目标类的实例,则直接返回;否则使用Factory
直接创建,并存入到ViewModelStore
中,以便后续获取。
说明:
ViewModelProviderImpl
的getViewModel(modelClass,key)
方法,key
默认为:androidx.lifecycle.ViewModelProvider.DefaultKey:全路径类名。
小结
说明:
ViewModelProvider
的get()
方法,其获取需要核心类ViewModelStore
(保存、获取ViewModel
)、ViewModelProvider.Factory
(创建ViewModel
)、CreationExtras
(辅助创建ViewModel
用)。ViewModelProvider
的get()
方法,支持通过,指定key
(默认为:androidx.lifecycle.ViewModelProvider.DefaultKey:全路径类名)、Class
或KClass
(二选一),获取对应的ViewModel
。其会先从ViewModelStore
中获取ViewModel
,如果有并且是目标类的实例,则直接返回;否则使用Factory
直接创建(CreationExtras
辅助创建),并存入到ViewModelStore
中,以便后续获取。
举例讲解:
以在androidx
的Activity
内获取无参构造方法ViewModel
为例,讲解代码流程。
声明ViewModel
class MyViewModel : ViewModel() {
override fun onCleared() {
super.onCleared()
}
}
获取ViewModel
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 获取ViewModel
val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
}
}
示例代码流程:
1. 创建ViewModelProvider
,传入的是ComponentActivity
,它的ViewModelStore
为ComponentActivity
提供的ViewModelStore
,它的Factory
为ComponentActivity
提供的默认Factory
(SavedStateViewModelFactory
),它的CreationExtras
为ComponentActivity
提供的默认CreationExtras
(MutableCreationExtras
,并有传入一些参数,用于创建SavedStateHandle
)。
2.ViewModelProvider
的get()
方法,先从ViewModelStore
中获取ViewModel
,如果有并且是目标类,则直接返回,否则使用Factory
(SavedStateViewModelFactory
)直接创建,并存入到ViewModelStore
中,以便后续获取。
3.SavedStateViewModelFactory
的create()
方法,最终会调用NewInstanceFactory
的create()
方法创建ViewModel
。(因为获取的MyViewModel
未使用SavedStateHandle
,所以会使用AndroidViewModelFactory
创建。又因为MyViewModel
未继承AndroidViewModel
,所以会使用NewInstanceFactory
创建)
viewModels()扩展方法
Activity
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline extrasProducer: (() -> CreationExtras)? = null,
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
// 传入的Factory为空,则使用ComponentActivity的defaultViewModelProviderFactory提供的值,详细见-获取Factory。
val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory }
return ViewModelLazy(
VM::class,
{ viewModelStore },
factoryPromise,
// 传入的CreationExtras为空,则使用ComponentActivity的defaultViewModelCreationExtras提供的值,详细见-获取CreationExtras。
{ extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras }
)
}
ComponentActivity
的viewModels()
扩展方法,最终调用的ViewModelLazy
类(详细讲解看下面)。
Fragment
// Fragment-viewModels
@MainThread
public inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
noinline extrasProducer: (() -> CreationExtras)? = null,
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val owner by lazy(LazyThreadSafetyMode.NONE) { ownerProducer() }
return createViewModelLazy(
VM::class,
{ owner.viewModelStore },
{
// 传入的CreationExtras不为空,就用传入的;
// 否则如果owner实现了HasDefaultViewModelProviderFactory,则用owner的defaultViewModelCreationExtras提供的默认值;
// 否则用空值。
extrasProducer?.invoke()
?: (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras
?: CreationExtras.Empty
},
// 传入的Factory不为空,就用传入的;
// 否则如果owner实现了HasDefaultViewModelProviderFactory,则用owner的defaultViewModelProviderFactory提供的默认值;
// 否则就用此Fragment的defaultViewModelProviderFactory提供的默认值。
factoryProducer ?: {
(owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelProviderFactory
?: defaultViewModelProviderFactory
})
}
// Fragment-activityViewModels
@MainThread
public inline fun <reified VM : ViewModel> Fragment.activityViewModels(
noinline extrasProducer: (() -> CreationExtras)? = null,
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> = createViewModelLazy(
VM::class,
{ requireActivity().viewModelStore },
// 传入的CreationExtras为空,则使用ComponentActivity的defaultViewModelProviderFactory提供的值。
{ extrasProducer?.invoke() ?: requireActivity().defaultViewModelCreationExtras },
// 传入的Factory为空,则使用ComponentActivity的defaultViewModelCreationExtras提供的值。
factoryProducer ?: { requireActivity().defaultViewModelProviderFactory }
)
// Fragment-createViewModelLazy
@MainThread
public fun <VM : ViewModel> Fragment.createViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
extrasProducer: () -> CreationExtras = { defaultViewModelCreationExtras },
factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
// 传入的Factory为空,用此Fragment的defaultViewModelProviderFactory提供的默认值。
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
return ViewModelLazy(viewModelClass, storeProducer, factoryPromise, extrasProducer)
}
Fragment
的viewModels()
、activityViewModels()
扩展方法,都是调用的createViewModelLazy()
扩展方法,其最终都是调用的ViewModelLazy
类,接下来我们来看下这个类。
ViewModelLazy类
public class ViewModelLazy<VM : ViewModel> @JvmOverloads constructor(
private val viewModelClass: KClass<VM>,
private val storeProducer: () -> ViewModelStore,
private val factoryProducer: () -> ViewModelProvider.Factory,
private val extrasProducer: () -> CreationExtras = { CreationExtras.Empty }
) : Lazy<VM> {
private var cached: VM? = null
override val value: VM
get() {
val viewModel = cached
return if (viewModel == null) {
val store = storeProducer()
val factory = factoryProducer()
val extras = extrasProducer()
// 通过create方式创建ViewModelProvider
ViewModelProvider.create(store, factory, extras)
// 获取
.get(viewModelClass)
// 保存到缓存,以标记已经初始化。
.also { cached = it }
} else {
viewModel
}
}
override fun isInitialized(): Boolean = cached != null
}
ViewModelLazy
类,是一个Lazy
类,其最终调用的ViewModelProvider.create()
创建的。
小结
说明:
ComponentActivity
的viewModels()
扩展方法、Fragment
的viewModels()
和activityViewModels()
扩展方法,最终都是调用的ViewModelLazy
类,其内部是使用ViewModelProvider.create()
创建的。
ViewModel是如何保持不变的?
Activity
和Fragment
在配置变更(如:屏幕旋转)的情况会销毁并重新创建,但是再次获取的ViewModel
实例不变。ViewModel
是从ViewModelStore
中获取的,我们分别看一下androidx
的Activity
和Fragment
的getViewModelStore()
方法。
Activity
ComponentActivity–> getViewModelStore方法
open class ComponentActivity() :
androidx.core.app.ComponentActivity(),
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
OnUserLeaveHintProvider,
MenuHost,
FullyDrawnReporterOwner {
private var _viewModelStore: ViewModelStore? = null
override val viewModelStore: ViewModelStore
get() {
// 不能在onCreate调用之前获取ViewModel
checkNotNull(application) {
("Your activity is not yet attached to the " +
"Application instance. You can't request ViewModel before onCreate call.")
}
// 确保ViewModelStore
ensureViewModelStore()
// 返回ViewModelStore
return _viewModelStore!!
}
private fun ensureViewModelStore() {
if (_viewModelStore == null) {
val nc = lastNonConfigurationInstance as NonConfigurationInstances?
if (nc != null) {
// 从 NonConfigurationInstances 中恢复ViewModelStore
_viewModelStore = nc.viewModelStore
}
if (_viewModelStore == null) {
// _viewModelStore为空,则创建。
_viewModelStore = ViewModelStore()
}
}
}
获取ViewModelStore
,我们先从lastNonConfigurationInstance
中获取,其内部包含了一个viewModelStore
,然后没有我们再重新创建新的ViewModelStore
。
说明:
1. 为什么ComponentActivity
的mViewModelStore
属性,在配置变更之前存入值,而在配置变更之后为空?
* 因为Activity
在配置变更之后,重新创建的Activity
,Activity
对象为新的,所以其mViewModelStore
属性为初始状态:空。
我们先来分析一下lastNonConfigurationInstance
是如何被获取的,然后再来看他是如何被赋值的。
lastNonConfigurationInstance
,是调用了Activity
的getLastNonConfigurationInstance()
方法。
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
要想getLastNonConfigurationInstance()
不为null
,首先的mLastNonConfigurationInstances
不为null
,我们先来看一下mLastNonConfigurationInstances
是如何被赋值的。
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
IBinder shareableActivityToken) {
attach(context, aThread, instr, token, ident, application, intent, info, title, parent, id,
lastNonConfigurationInstances, config, referrer, voiceInteractor, window,
activityConfigCallback, assistToken, shareableActivityToken, null);
}
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
IBinder shareableActivityToken, IBinder initialCallerInfoAccessToken) {
...
mLastNonConfigurationInstances = lastNonConfigurationInstances;
...
}
经过查找得知mLastNonConfigurationInstances
,是在Activity
的attach()
方法被赋值的。
接下来,我们通过查看Activity
的onCreate()
调用栈的方式,分析普通开启Activity
和配置变更(如:屏幕旋转)开启Activity
的区别。
普通开启Activity的onCreate()的调用栈
onCreate:11, MainActivity (com.zrq.demo)
performCreate:8290, Activity (android.app)
performCreate:8269, Activity (android.app)
callActivityOnCreate:1384, Instrumentation (android.app)
performLaunchActivity:3657, ActivityThread (android.app)
handleLaunchActivity:3813, ActivityThread (android.app)
execute:101, LaunchActivityItem (android.app.servertransaction)
executeCallbacks:135, TransactionExecutor (android.app.servertransaction)
execute:95, TransactionExecutor (android.app.servertransaction)
handleMessage:2308, ActivityThread$H (android.app)
dispatchMessage:106, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7898, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:936, ZygoteInit (com.android.internal.os)
配置变更(如:屏幕旋转)开启Activity的onCreate()的调用栈
onCreate:11, MainActivity (com.zrq.demo)
performCreate:8290, Activity (android.app)
performCreate:8269, Activity (android.app)
callActivityOnCreate:1384, Instrumentation (android.app)
performLaunchActivity:3657, ActivityThread (android.app)
handleLaunchActivity:3813, ActivityThread (android.app)
handleRelaunchActivityInner:5791, ActivityThread (android.app)
handleRelaunchActivity:5682, ActivityThread (android.app)
execute:71, ActivityRelaunchItem (android.app.servertransaction)
execute:45, ActivityTransactionItem (android.app.servertransaction)
executeCallbacks:135, TransactionExecutor (android.app.servertransaction)
execute:95, TransactionExecutor (android.app.servertransaction)
handleMessage:2308, ActivityThread$H (android.app)
dispatchMessage:106, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7898, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:936, ZygoteInit (com.android.internal.os)
两者差异对比
我们先来看一下普通开启Activity的onCreate()的调用栈关键代码流程,然后再来看配置变更(如:屏幕旋转)开启Activity的onCreate()的调用栈关键代码流程。
普通开启Activity的onCreate()的调用栈关键代码流程
...
performLaunchActivity:3657, ActivityThread (android.app)
handleLaunchActivity:3813, ActivityThread (android.app)
execute:101, LaunchActivityItem (android.app.servertransaction) // 差异
...
LaunchActivityItem–> execute方法
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
mTaskFragmentToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
创建了ActivityClientRecord
(其内部属性lastNonConfigurationInstances
是没有赋值的,为null
),并传递给了ActivityThread
(继承了ClientTransactionHandler
类)的handleLaunchActivity()
方法。
ActivityThread–> handleLaunchActivity方法
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
return a;
}
将值,继续传递给了ActivityThread
的performLaunchActivity()
方法。
ActivityThread–> performLaunchActivity方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
try {
...
synchronized (mResourcesManager) {
// 存到mActivities中
mActivities.put(r.token, r);
}
if (activity != null) {
...
// 将lastNonConfigurationInstances传递给了activity
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
r.assistToken, r.shareableActivityToken);
...
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
将上面刚创建ActivityClientRecord
(无lastNonConfigurationInstances
)的存到ActivityThread
的mActivities
集合中,并通过activity.attach()
方法将ActivityClientRecord
的lastNonConfigurationInstance
(为空)传递给Activity
。
ActivityThread–> mActivities
public final class ActivityThread extends ClientTransactionHandler
implements ActivityThreadInternal {
@UnsupportedAppUsage
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
}
普通开启Activity总结
说明:
- 普通开启
Activity
:创建一个新的ActivityClientRecord
(无lastNonConfigurationInstances
),并存到ActivityThread
的mActivities
集合中,并通过activity.attach()
方法将ActivityClientRecord
的lastNonConfigurationInstance
(为空)传递给Activity
。
配置变更(如:屏幕旋转)开启Activity的onCreate()的调用栈关键代码流程
...
performLaunchActivity:3657, ActivityThread (android.app)
handleLaunchActivity:3813, ActivityThread (android.app)
handleRelaunchActivityInner:5791, ActivityThread (android.app) // 差异
handleRelaunchActivity:5682, ActivityThread (android.app) // 差异
execute:71, ActivityRelaunchItem (android.app.servertransaction) // 差异
execute:45, ActivityTransactionItem (android.app.servertransaction) // 差异
...
ActivityTransactionItem–> execute方法
@Override
public final void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
final ActivityClientRecord r = getActivityClientRecord(client, token);
execute(client, r, pendingActions);
}
@NonNull ActivityClientRecord getActivityClientRecord(
@NonNull ClientTransactionHandler client, IBinder token) {
final ActivityClientRecord r = client.getActivityClient(token);
...
return r;
}
ActivityTransactionItem
的execute()
方法,通过client
(ActivityThread
)的getActivityClient()
获取ActivityClientRecord
,并传给了ActivityRelaunchItem
的execute()
方法。
ActivityThread–> getActivityClient方法
@Override
public ActivityClientRecord getActivityClient(IBinder token) {
return mActivities.get(token);
}
ActivityRelaunchItem–> execute方法
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults,
mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow);
}
@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
PendingTransactionActions pendingActions) {
if (mActivityClientRecord == null) {
if (DEBUG_ORDER) Slog.d(TAG, "Activity relaunch cancelled");
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
client.handleRelaunchActivity(mActivityClientRecord, pendingActions);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ActivityRelaunchItem
的execute()
方法,他会将preExecute()
方法获取的mActivityClientRecord
传递给ActivityThread
的handleRelaunchActivity()
方法。
说明:
preExecute()
方法,是调用了client
(ActivityThread
)的prepareRelaunchActivity()
获取ActivityClientRecord
。其内部是先判断mRelaunchingActivities
内部是否有此token
的,如果有则返回;如果没有则创建一个新的ActivityClientRecord
,并将token
赋值给他,并把他添加到mRelaunchingActivities
中。保证了会获取到token
相同的ActivityClientRecord
,在此就不展示源码了。
ActivityThread–> handleRelaunchActivity方法
@Override
public void handleRelaunchActivity(ActivityClientRecord tmp,
PendingTransactionActions pendingActions) {
...
ActivityClientRecord r = mActivities.get(tmp.token);
...
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
...
}
ActivityThread
的handleRelaunchActivity()
方法, 其内部调用了ActivityThread
的handleRelaunchActivityInner()
方法。
说明:
mActivities.get(tmp.token)
,tmp
是在上面通过ActivityThread
的prepareRelaunchActivity()
方法获取的临时ActivityClientRecord
,其保证了两者token
相同,所以在此通过tmp.token
从mActivities
中获取,也是能获取到ActivityClientRecord
的。
ActivityThread–> handleRelaunchActivityInner方法
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
...
handleDestroyActivity(r, false, configChanges, true, reason);
...
handleLaunchActivity(r, pendingActions, customIntent);
}
ActivityThread
的handleRelaunchActivityInner()
方法, 其内部先调用了处理销毁方法handleDestroyActivity()
(getNonConfigInstance
参数为ture
),然后调用了处理启动方法handleLaunchActivity()
。
ActivityThread
的handleLaunchActivity()
方法,已经在上面讲解了(详细看上面:普通开启Activity),我们接下来先看ActivityThread
的handleDestroyActivity()
方法。
ActivityThread–> handleDestroyActivity方法
@Override
public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
...
}
ActivityThread
的handleDestroyActivity()
方法,其内部调用了ActivityThread
的performDestroyActivity()
方法(getNonConfigInstance
参数为ture
)。
ActivityThread–> performDestroyActivity方法
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
...
if (getNonConfigInstance) {
try {
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
...
}
}
...
synchronized (mResourcesManager) {
mActivities.remove(r.token);
}
...
}
ActivityThread
的performDestroyActivity()
方法,其内部判断了,如果getNonConfigInstance
为true
(此传入为true
),则将Activity
的retainNonConfigurationInstances()
方法的结果,保存在此ActivityClientRecord
的lastNonConfigurationInstances
属性上,并将其ActivityClientRecord
在mActivities
中移除。
配置变更(如:屏幕旋转)开启Activity总结
说明:
- 配置变更(如:屏幕旋转)开启
Activity
:
performDestroyActivity()
:将获取的ActivityClientRecord
(无lastNonConfigurationInstances
),将Activity
的retainNonConfigurationInstances()
方法的结果,保存到其lastNonConfigurationInstances
属性上,并将其在mActivities
中移除。handleLaunchActivity()
:将获取的ActivityClientRecord
(有lastNonConfigurationInstances
),存到ActivityThread
的mActivities
集合中,并通过activity.attach()
方法将ActivityClientRecord
的lastNonConfigurationInstance
(为空)传递给Activity
。
总结
说明:
- 普通开启
Activity
:Activity
的mLastNonConfigurationInstances
为null
。- 配置变更(如:屏幕旋转)开启
Activity
:Activity
的mLastNonConfigurationInstances
不为null
,其值为此Activity
的retainNonConfigurationInstances()
方法返回的值(Activity
销毁时保存的)。
接下来,我们来一起看一下Activity
的retainNonConfigurationInstances()
方法,看下其内部都保存了什么。
Activity–> retainNonConfigurationInstances方法
NonConfigurationInstances retainNonConfigurationInstances() {
// 获取到当前Activity要保存的数据
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
// We're already stopped but we've been asked to retain.
// Our fragments are taken care of but we need to mark the loaders for retention.
// In order to do this correctly we need to restart the loaders first before
// handing them off to the next activity.
mFragments.doLoaderStart();
mFragments.doLoaderStop(true);
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity; // 记录当前Activity要保存的数据
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
Activity.NonConfigurationInstances类
static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
FragmentManagerNonConfig fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
Actiity
的retainNonConfigurationInstances()
方法,为保留不会因配置变更而销毁的对象。其NonConfigurationInstances
类的activity
,记录当前Activity
要保存的数据。
我们接下来,看一下Activity
的onRetainNonConfigurationInstance()
方法,其默认空实现,我们看一下他的实现类ComponentActivity
的onRetainNonConfigurationInstance()
方法。
ComponentActivity–> onRetainNonConfigurationInstance方法
final override fun onRetainNonConfigurationInstance(): Any? {
// Maintain backward compatibility.
val custom = onRetainCustomNonConfigurationInstance()
var viewModelStore = _viewModelStore
if (viewModelStore == null) {
// viewModelStore为空,则说明此时没有调用过getViewModelStore(),则通过getLastNonConfigurationInstance()从重建之前的获取。
val nc = lastNonConfigurationInstance as NonConfigurationInstances?
if (nc != null) {
viewModelStore = nc.viewModelStore
}
}
if (viewModelStore == null && custom == null) {
return null
}
val nci = NonConfigurationInstances()
nci.custom = custom
nci.viewModelStore = viewModelStore // 记录当前viewModelStore
return nci
}
ComponentActivity.NonConfigurationInstances类
internal class NonConfigurationInstances {
var custom: Any? = null
var viewModelStore: ViewModelStore? = null
}
ComponentActivity
的onRetainNonConfigurationInstance()
方法(Activity
销毁时调用),内部保存了在配置变更之前维护的ViewModelStore
。
说明:
Activity
的mLastNonConfigurationInstances
(即Activity.NonConfigurationInstances
)的activity
(即ComponentActivity.NonConfigurationInstances
)的viewModelStore
,保存了在配置变更之前维护的ViewModelStore
。lastNonConfigurationInstance
,是调用的getLastNonConfigurationInstance()
方法,其内部获取的是mLastNonConfigurationInstances.activity
。
小结
配置变更重启Activity-ViewModel保持不变的代码流程:
- 配置变更重启
Activity
,会走ActivityThread.handleRelaunchActivity()
方法,其(具体handleRelaunchActivityInner()
)内部会先走销毁流程,后走启动流程。此处调用的销毁流程会传入参数getNonConfigInstance
为true
,以标记会获取NonConfigurationInstances
的值(既流程2的值)。- 在
ActivityThread.performDestroyActivity()
方法,ActivityClientRecord.lastNonConfigurationInstances
保存了Activity.retainNonConfigurationInstances()
方法返回的Activity.NonConfigurationInstances
对象。- 其中的
Activity.NonConfigurationInstances.activity
属性,保存了ComponentActivity.onRetainNonConfigurationInstance()
方法返回的ComponentActivity.NonConfigurationInstances
对象。- 其中的
ComponentActivity.NonConfigurationInstances.viewModelStore
属性,保存了在配置变更之前维护的ViewModelStore
。- 在
ActivityThread.performLaunchActivity()
方法,调用Activity.attach()
方法,传入了保存在ActivityClientRecord.lastNonConfigurationInstances
的Activity.NonConfigurationInstances
对象。Activity.attach()
方法,保存了传入的Activity.NonConfigurationInstances
对象。- 通过调用
Activity.getLastNonConfigurationInstance()
方法,即可拿到Activity.NonConfigurationInstances.activity
属性保存的ComponentActivity.NonConfigurationInstances
对象。- 最后
ComponentActivity
通过获取getLastNonConfigurationInstance().viewModelStore
属性的值,即可拿到在配置变更之前维护的ViewModelStore
,并且获取到的ViewModelStore
实例不变(即获取的ViewModel
实例不变)。简化流程:
- 配置变更重启
Activity
,会走ActivityThread.handleRelaunchActivity()
方法,其内部会先走销毁流程(标记会获取下面的值),后走启动流程。- 在
Activity
销毁的时候,ActivityClientRecord.lastNonConfigurationInstances.activity.viewModelStore
属性,保存了在配置变更之前维护的ViewModelStore
。- 在
Activity
启动的时候,ActivityClientRecord.lastNonConfigurationInstances
的值在Activity.attach()
的时候被存入到了Activity
中,所以后续也能获取到在配置变更之前维护的ViewModelStore
,并且获取到的ViewModelStore
实例不变(即获取的ViewModel
实例不变)。
Fragment
Fragment –> getViewModelStore方法
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (mFragmentManager == null) {
// 不能从detached的Fragment访问ViewModels
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
if (getMinimumMaxLifecycleState() == Lifecycle.State.INITIALIZED.ordinal()) {
throw new IllegalStateException("Calling getViewModelStore() before a Fragment "
+ "reaches onCreate() when using setMaxLifecycle(INITIALIZED) is not "
+ "supported");
}
return mFragmentManager.getViewModelStore(this);
}
mFragmentManager
为FragmentManager
,我们来看下其getViewModelStore()
方法。
FragmentManager –> getViewModelStore方法
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
return mNonConfig.getViewModelStore(f);
}
mNonConfig
为FragmentManagerViewModel
,我们先来看一下它是如何创建的,然后再来看一下其getViewModelStore()
方法。
通过查看,发现其在FragmentManager.attachController()
方法内创建。
FragmentManager –> attachController方法
@SuppressWarnings("deprecation")
@SuppressLint("SyntheticAccessor")
void attachController(@NonNull FragmentHostCallback<?> host,
@NonNull FragmentContainer container, @Nullable final Fragment parent) {
...
// Get the FragmentManagerViewModel
if (parent != null) {
// 当parent不为null时,调用父FragmentManager的getChildNonConfig获取。
mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
} else if (host instanceof ViewModelStoreOwner) {
// 从host中获取ViewModelStore,然后使用FragmentManagerViewModel进行获取。
ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
} else {
mNonConfig = new FragmentManagerViewModel(false);
}
...
}
通过查看调用栈,发现attachController()
方法会在Activity
的onCreate()
、Fragment
的performAttach()
的时候调用,其中host
为FragmentActivity
的内部类FragmentActivity.HostCallbacks
(持有外部类FragmentActivity
,可以调用其方法),它实现了ViewModelStoreOwner
接口。
创建mNonConfig
,如果是Activity
的FragmentManager
,其会走第二个if
创建;如果是Fragment
的FragmentManager
,其会走第一个if
创建。
我们以Activity
的为例,先来看一下FragmentActivity.HostCallbacks
的getViewModelStore()
方法,然后再来看一下FragmentManagerViewModel
的getInstance()
方法。
FragmentActivity.HostCallbacks –> getViewModelStore方法
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
ViewModelStoreOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
SavedStateRegistryOwner,
FragmentOnAttachListener,
MenuHost {
...
@NonNull
@Override
public ViewModelStore getViewModelStore() {
return FragmentActivity.this.getViewModelStore();
}
...
}
FragmentActivity.HostCallbacks
类,实现了ViewModelStoreOwner
接口,其getViewModelStore()
方法,直接调用了外部类FragmentActivity
的getViewModelStore()
方法,所以能获取到ViewModelStore
。
接下来,我们再来看一下FragmentManagerViewModel
的getInstance()
方法。
FragmentManagerViewModel –> getInstance方法
final class FragmentManagerViewModel extends ViewModel {
private static final String TAG = FragmentManager.TAG;
private static final ViewModelProvider.Factory FACTORY = new ViewModelProvider.Factory() {
@NonNull
@Override
@SuppressWarnings("unchecked")
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
FragmentManagerViewModel viewModel = new FragmentManagerViewModel(true);
return (T) viewModel;
}
};
@NonNull
static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore,
FACTORY);
return viewModelProvider.get(FragmentManagerViewModel.class);
}
}
FragmentManagerViewModel
是一个ViewModel
,getInstance(ViewModelStore)
方法会先从传入的ViewModelStore
(即ComponentActivity
的ViewModelStore
)中获取,如果没有则再使用FACTORY
进行创建FragmentManagerViewModel
。
说明:
1. 传入的ViewModelStore
为ComponentActivity
的ViewModelStore
,一开始ViewModelStore
内是没有FragmentManagerViewModel
的,所以创建FragmentManagerViewModel
并存入其ComponentActivity
的ViewModelStore
中。
2. 由于ComponentActivity
的ViewModelStore
配置变更后实例不变,所以FragmentManagerViewModel.getInstance()
方法也能从ComponentActivity
的ViewModelStore
中获取到配置变更前存入的FragmentManagerViewModel
实例。
说完了FragmentManagerViewModel
的创建,我们再来看一下其getViewModelStore()
方法。
FragmentManagerViewModel –> getViewModelStore方法
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
getViewModelStore(Fragment)
方法,获取到指定Fragment
的ViewModelStore
,如果mViewModelStores
中有则返回,如果没有则进行创建并保存到mViewModelStores
中,mViewModelStores
为ViewModelStore
的Map
集合。
说明:
1. 为什么FragmentManagerViewModel.getViewModelStore(Fragment)
方法,要传入Fragment
才能获取到ViewModelStore
?
* 因为FragmentManagerViewModel
,保存到了ComponentActivity
的ViewModelStore
中,导致每个Fragment
获取到的FragmentManagerViewModel
实例相同,所以需要传入Fragment
实例区分是获取哪个ViewModelStore
。
2. 为什么Fragment
在配置变更前后获取到的ViewModelStore
、ViewModel
实例不变?
* 因为ComponentActivity
在配置变更前后获取到的ViewModelStore
、ViewModel
实例不变,因此存在ComponentActivity
的ViewModelStore
中的FragmentManagerViewModel
实例不变,所以存在mViewModelStores
的各个Fragment
的ViewModelStore
实例不变(即获取的ViewModel
实例不变)。
小结
配置变更重启Fragment-ViewModel保持不变的代码流程:
- 在
Fragment.getViewModelStore()
方法,会通过FragmentManager.getViewModelStore(Fragment)
获取。- 而
FragmentManager.getViewModelStore(Fragment)
方法,会通过mNonConfig.getViewModelStore(Fragment)
获取。- 而
FragmentManager.mNonConfig
属性,是FragmentManagerViewModel
类,是一个ViewModel
,其是在FragmentManager.attachController()
方法内创建的。- 我们先讲
FragmentManagerViewModel
的创建,然后讲FragmentManagerViewModel
的获取ViewModelStore
。FragmentManagerViewModel
的创建:
- 如果是
ComponentActivity
的FragmentManager
创建mNonConfig
,则是通过FragmentManagerViewModel.getInstance(viewModelStore)
方法创建,参数viewModelStore
为获取的当前Activity
内ViewModelStore
。(如果是Fragment
的FragmentManager
创建mNonConfig
,这里没做讲解)FragmentManagerViewModel.getInstance(viewModelStore)
方法,内部是使用ViewModelProvider
的get()
方法获取的。既会先从参数viewModelStore
中获取此FragmentManagerViewModel
,如果有则返回,如果没有则再进行创建并添加到此viewModelStore
中(即将创建的FragmentManagerViewModel
存到当前Activity
内ViewModelStore
中,保证了一个Activity
内仅有一个FragmentManagerViewModel
)。FragmentManagerViewModel
的获取ViewModelStore
:
FragmentManagerViewModel.getViewModelStore(Fragment)
方法,获取到指定Fragment
的ViewModelStore
,如果mViewModelStores
中有则返回,如果没有则进行创建并保存到mViewModelStores
中。FragmentManagerViewModel.mViewModelStores
属性,为ViewModelStore
的Map
集合,key
为String
,value
为ViewModelStore
,用于记录一个Fragment
对应一个ViewModelStore
。- 说明:
ComponentActivity
内自己维护了一个ViewModelStore
。Fragment
内没有维护了一个ViewModelStore
,而是通过获取ComponentActivity
的ViewModelStore
内的FragmentManagerViewModel
(没有则会创建并添加),通过其维护的mViewModelStores
获取当前Fragment
对应的ViewModelStore
(没有则会创建并添加)。- 因为
ComponentActivity
在配置变更前后获取到的ViewModelStore
、ViewModel
实例不变,因此存在ComponentActivity
的ViewModelStore
中的FragmentManagerViewModel
实例不变,所以存在mViewModelStores
的各个Fragment
的ViewModelStore
实例不变(即从Fragment
中获取的ViewModel
实例不变)。简化流程:
Fragment
获取ViewModelStore
,是通过FragmentManagerViewModel
获取的,其存放在当前ComponentActivity
的ViewModelStore
中(没有则会创建并添加)。FragmentManagerViewModel.getViewModelStore(Fragment)
方法,获取到指定Fragment
的ViewModelStore
,没有则会创建并添加到mViewModelStores
中。mViewModelStores
为ViewModelStore
的Map
集合,用于记录一个Fragment
对应一个ViewModelStore
。- 因为
ComponentActivity
在配置变更前后获取到的ViewModelStore
、ViewModel
实例不变,因此存在ComponentActivity
的ViewModelStore
中的FragmentManagerViewModel
实例不变,所以存在mViewModelStores
的各个Fragment
的ViewModelStore
实例不变(即从Fragment
中获取的ViewModel
实例不变)。
ViewModel是如何被清除的?
要想分析ViewModel
是如何被清除的,则需要分析ViewModelStore
是如何被清除的。
Activity
通过查找,我们发现在ComponentActivity
的init
方法里面调用了ViewModelStore
的clear()
清除操作。
ComponentActivity类
open class ComponentActivity() :
androidx.core.app.ComponentActivity(),
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller,
OnConfigurationChangedProvider,
OnTrimMemoryProvider,
OnNewIntentProvider,
OnMultiWindowModeChangedProvider,
OnPictureInPictureModeChangedProvider,
OnUserLeaveHintProvider,
MenuHost,
FullyDrawnReporterOwner {
init {
...
@Suppress("LeakingThis")
lifecycle.addObserver(
LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
contextAwareHelper.clearAvailableContext()
// And clear the ViewModelStore
if (!isChangingConfigurations) {
// 不是配置变更,清除全部ViewModel。
viewModelStore.clear()
}
reportFullyDrawnExecutor.activityDestroyed()
}
}
)
...
}
}
使用Lifecycle
观察当前生命周期的状态,如果事件处于ON_DESTROY
并且不是配置变更,则清空全部ViewModel
。
说明:
1.Activity
的ViewModel
是如何被清除的?
Activity
初始化的时候,使用Lifecycle
观察当前生命周期的状态,如果事件处于ON_DESTROY
并且不是配置变更,则清空全部ViewModel
。
Fragment
通过调用查找,我们发现在FragmentManagerViewModel
的clearNonConfigStateInternal()
方法里面调用了ViewModelStore
的clear()
清除操作。
FragmentManagerViewModel –> clearNonConfigStateInternal方法
void clearNonConfigState(@NonNull Fragment f, boolean destroyChildNonConfig) {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Clearing non-config state for " + f);
}
clearNonConfigStateInternal(f.mWho, destroyChildNonConfig);
}
private void clearNonConfigStateInternal(@NonNull String who, boolean destroyChildNonConfig) {
// Clear and remove the Fragment's child non config state
FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(who);
if (childNonConfig != null) {
// destroy child nonConfig immediately if it hasn't gone through init
if (destroyChildNonConfig) {
ArrayList<String> clearList = new ArrayList<>();
clearList.addAll(childNonConfig.mChildNonConfigs.keySet());
for (String childWho : clearList) {
childNonConfig.clearNonConfigState(childWho, true);
}
}
childNonConfig.onCleared();
mChildNonConfigs.remove(who);
}
// 获取到对应Fragment的ViewModelStore
ViewModelStore viewModelStore = mViewModelStores.get(who);
if (viewModelStore != null) {
// 清除全部ViewModel。
viewModelStore.clear();
mViewModelStores.remove(who);
}
}
clearNonConfigStateInternal(String)
方法,会获取到对应Fragment
的ViewModelStore
,然后调用其clear()
方法清除全部ViewModel
。
通过调用查找,我们发现在clearNonConfigStateInternal(String)
方法被clearNonConfigState()
方法调用,最后通过Debug
查看调用栈发现FragmentStateManager.destroy()
方法,执行了clearNonConfigState(Fragment)
方法。
FragmentStateManager –> destroy方法
void destroy() {
...
if (shouldDestroy) {
FragmentHostCallback<?> host = mFragment.mHost;
boolean shouldClear;
if (host instanceof ViewModelStoreOwner) {
shouldClear = mFragmentStore.getNonConfig().isCleared();
} else if (host.getContext() instanceof Activity) {
Activity activity = (Activity) host.getContext();
shouldClear = !activity.isChangingConfigurations();
} else {
shouldClear = true;
}
if ((beingRemoved && !mFragment.mBeingSaved) || shouldClear) {
// 执行FragmentManagerViewModel的clearNonConfigState(),清除不会因配置变更而改变的状态。
mFragmentStore.getNonConfig().clearNonConfigState(mFragment, false);
}
...
}
...
}
host
为FragmentActivity.HostCallbacks
,它实现了ViewModelStoreOwner
接口,所以会走第一个if
。只要shouldClear
为true
的时候,就会执行到FragmentManagerViewModel
的clearNonConfigState(Fragment)
方法,我们来看一下FragmentManagerViewModel
的isCleared()
方法的返回值是什么?
FragmentManagerViewModel –> isCleared方法
final class FragmentManagerViewModel extends ViewModel {
@Override
protected void onCleared() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "onCleared called for " + this);
}
// 标记已经被清理
mHasBeenCleared = true;
}
boolean isCleared() {
return mHasBeenCleared;
}
}
FragmentManagerViewModel
是一个ViewModel
,被添加到了ComponentActivity
的ViewModelStore
中,当ComponentActivity
的ViewModelStore
被清除的时候(事件为ON_DESTROY
并且不是配置变更),会调用ViewModel
的onCleared()
方法,则mHasBeenCleared
为true
,即isCleared()
方法返回为true
。
因为isCleared()
方法返回为true
,所以FragmentStateManager.destroy()
方法内会执行到FragmentManagerViewModel
的clearNonConfigState()
方法,会获取到对应Fragment
的ViewModelStore
,然后调用其clear()
方法清除全部ViewModel
。
说明:
1.Fragment
的ViewModel
是如何被清除的?
*FragmentManagerViewModel
是一个ViewModel
,被添加到了ComponentActivity
的ViewModelStore
中,当ComponentActivity
的ViewModelStore
被清除的时候(事件为ON_DESTROY
并且不是配置变更),会调用ViewModel
的onCleared()
方法,则mHasBeenCleared
为true
,即isCleared()
方法返回为true
,所以FragmentStateManager.destroy()
方法内会执行到FragmentManagerViewModel
的clearNonConfigState(Fragment)
方法,会获取到对应Fragment
的ViewModelStore
,然后调用其clear()
方法清除全部ViewModel
。
小结
ViewModel是如何被清除的?
Activity
:Activity
初始化的时候,使用Lifecycle
观察当前生命周期的状态,如果事件处于ON_DESTROY
并且不是配置变更,则清空全部ViewModel
。Fragment
:FragmentManagerViewModel
是一个ViewModel
,被添加到了ComponentActivity
的ViewModelStore
中,当Fragment
销毁的时候,会判断此ViewModel
是否被消除,如果被消除(既ComponentActivity
被销毁并且不是配置变更),则会获取到此Fragment
的ViewModelStore
,然后调用其clear()
方法清除全部ViewModel
。
总结
以上就是全面的Jetpack-ViewModel
源码了!欢迎大家点赞、收藏,以方便您后续查看,之后会出Jetpack
其它源码系列,请及时关注。