ViewModel源码解析
源码版本:
- ViewModel:2.4.0
- Android:31
- androidx.activity:activity:1.4.0
- androidx.fragment:fragment:1.4.0
需会使用:
Lifecycle
导航:
使用
声明ViewModel
class MyViewModel : ViewModel() {
override fun onCleared() {
super.onCleared()
}
}
获取ViewModel
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 获取ViewModel
val model = ViewModelProvider(this).get(MyViewModel::class.java)
// observe
model.getUsers().observe(this, Observer<List<User>>{ users ->
// update UI
})
}
}
ViewModel生命周期
源码
声明ViewModel
ViewModel类
public abstract class ViewModel {
// 标签集合
@Nullable
private final Map<String, Object> mBagOfTags = new HashMap<>();
// 标记是否是已清除
private volatile boolean mCleared = false;
// 当ViewModel被清除时调用
protected void onCleared() {
}
@MainThread
final void clear() {
mCleared = true;
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);
}
}
}
onCleared();
}
// 添加数据key、value,如果key的值已经存在,则返回已存在的值,否则添加新的值。
// 并判断如果ViewModel是已被清除的,则返回的值如果是Closeable,就会调用close方法释放。即ViewModel已经被清除,再添加新的,则也会释放。
@SuppressWarnings("unchecked")
<T> T setTagIfAbsent(String key, T newValue) {
T previous;
synchronized (mBagOfTags) {
previous = (T) mBagOfTags.get(key);
if (previous == null) {
mBagOfTags.put(key, newValue);
}
}
T result = previous == null ? newValue : previous;
if (mCleared) {
closeWithRuntimeException(result);
}
return result;
}
// 获取被添加的数据
<T> T getTag(String key) {
if (mBagOfTags == null) {
return null;
}
synchronized (mBagOfTags) {
return (T) mBagOfTags.get(key);
}
}
private static void closeWithRuntimeException(Object obj) {
if (obj instanceof Closeable) {
// 是Closeable子类,则调用close关闭。
try {
((Closeable) obj).close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
ViewModel被清除的时候,会清空Tag并调用onCleared方法通知ViewModel被清除。
获取ViewModel
使用
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 获取ViewModel
val model = ViewModelProvider(this).get(MyViewModel::class.java)
// observe
model.getUsers().observe(this, Observer<List<User>>{ users ->
// update UI
})
}
}
获取ViewModel,首先需要创建ViewModelProvider,然后再调用其get方法获取,我们先来看一下ViewModelProvider对象是如果创建的,然后再看get方法是如果获取的。
ViewModelProvider构造方法
ViewModelProvider构造方法
public open class ViewModelProvider(
private val store: ViewModelStore,
private val factory: Factory
) {
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner))
public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
owner.viewModelStore,
factory
)
}
ViewModelProvider为ViewModel提供者,创建它需要ViewModelStore和ViewModelProvider.Factory,而ViewModelStore又可以从ViewModelStoreOwner中获取,我们分别来看下这几个类。
ViewModelStore
ViewModelStore类
public class ViewModelStore {
// ViewModel集合
private final HashMap<String, ViewModel> mMap = new HashMap<>();
TestViewModel
// 保存ViewModel,如果key已经存在,则值进行覆盖,之前的ViewModel则调用onCleared清空逻辑。
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
// 获取ViewModel
final ViewModel get(String key) {
return mMap.get(key);
}
// 获取所有的key
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
// 清除内部存储并通知ViewModels它们不再使用。
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
ViewModelProvider为ViewModel商店,它是用来存储或获取ViewModel的,是使用HashMap来实现的。其clear方法会清除内部存储并通知ViewModels它们不再使用。
ViewModelStoreOwner
ViewModelStoreOwner类
public interface ViewModelStoreOwner {
@NonNull
ViewModelStore getViewModelStore();
}
ViewModelStoreOwner为ViewModelStore的持有者,通过它的子类可以获取到ViewModelStore。androidx的Activity和Fragment都已经实现了ViewModelStoreOwner,我们分别看一下具体实现。
Activity
androidx.activity.ComponentActivity类
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller {
private ViewModelStore mViewModelStore;
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
// 不能在onCreate调用之前获取ViewModel
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
// 确保ViewModelStore
ensureViewModelStore();
// 返回ViewModelStore
return mViewModelStore;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// 从 NonConfigurationInstances 中恢复ViewModelStore
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
// mViewModelStore为空,则创建。
mViewModelStore = new ViewModelStore();
}
}
}
}
androidx Activity获取ViewModelStore,先从 NonConfigurationInstances 中恢复ViewModelStore(确保Activity重建后还能获取到之前的ViewModelStore,具体分析看下面ViewModel是如何保持不变的?),如果还是没有,则进行创建。
说明:
androidxActivity不能在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) {
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获取ViewModelStore,先获取到 FragmentManagerViewModel(确保Fragment重建后还能获取到之前的ViewModelStore,具体分析看下面ViewModel是如何保持不变的?),然后再从其mViewModelStores中获取,如果没有,则进行创建。
说明:
androidxFragment不能在onDetach调用之后获取ViewModel。
ViewModelProvider.Factory
ViewModelProvider.Factory类
public interface Factory {
// 创建给定ViewModel Class的新实例。
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
ViewModelProvider.Factory为ViewModel的创建工厂,此Factory通过ViewModel类的class,创建ViewModel实例。我们分别来看一下它的子类KeyedFactory、NewInstanceFactory、AndroidViewModelFactory。
ViewModelProvider.KeyedFactory
ViewModelProvider.KeyedFactory类
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public abstract class KeyedFactory : OnRequeryFactory(), Factory {
public abstract fun <T : ViewModel> create(
key: String,
modelClass: Class<T>
): T
override fun <T : ViewModel> create(modelClass: Class<T>): T {
throw UnsupportedOperationException(
"create(String, Class<?>) must be called on implementations of KeyedFactory"
)
}
}
KeyedFactory为Factory 的抽象子类,重写了create(Class<?>)方法,并且KeyedFactory子类必须重写create( Class<?>)方法并应该调用其create(String, Class<?>)方法。
ViewModelProvider.NewInstanceFactory
ViewModelProvider.NewInstanceFactory类
public open class NewInstanceFactory : Factory {
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return try {
// 通过反射获取实例
modelClass.newInstance()
} 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
// 单例 NewInstanceFactory
@JvmStatic
public val instance: NewInstanceFactory
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
get() {
if (sInstance == null) {
sInstance = NewInstanceFactory()
}
return sInstance!!
}
}
}
NewInstanceFactory为Factory 的子类,实现了create(Class<?>)方法,通过ViewModel类的class,无参反射创建ViewModel实例。
说明:
- 使用
NewInstanceFactory创建,此ViewModel必须有无参的且不是私有的构造方法。
- 可以处理如下
ViewModel:
class MyViewModel : ViewModel()
NewInstanceFactory.instance为全局单例NewInstanceFactory,防止了每次创建工厂,优化了性能。
ViewModelProvider.AndroidViewModelFactory
ViewModelProvider.AndroidViewModelFactory类
public open class AndroidViewModelFactory(
private val application: Application
) : NewInstanceFactory() {
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
try {
// 此ViewModel为AndroidViewModel的子类,则传入Application并创建。
modelClass.getConstructor(Application::class.java).newInstance(application)
} 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 {
// 获取默认工厂,如果owner有默认工厂则用owner的,否则用NewInstanceFactory工厂(反射创建)。
internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =
if (owner is HasDefaultViewModelProviderFactory)
owner.defaultViewModelProviderFactory else instance
// 获取的默认Key
internal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"
private var sInstance: AndroidViewModelFactory? = null
// 单例 AndroidViewModelFactory
@JvmStatic
public fun getInstance(application: Application): AndroidViewModelFactory {
if (sInstance == null) {
sInstance = AndroidViewModelFactory(application)
}
return sInstance!!
}
}
}
AndroidViewModelFactory为NewInstanceFactory 的子类,重写了create(Class<?>)方法,通过ViewModel类的class判断,如果此ViewModel为AndroidViewModel的子类,则传入Application并反射创建,否则走父类逻辑无参反射创建ViewModel实例。
说明:
- 使用
AndroidViewModelFactory创建,如果此ViewModel是AndroidViewModel子类,必须有一参的且是Application且不是私有的构造方法(不能无参);否则必须有无参的且不是私有的构造方法(不能有参)。
- 可以处理如下
ViewModel:
class MyViewModel : ViewModel()
class MyViewModel(application: Application) : AndroidViewModel(application)
AndroidViewModelFactory.getInstance为全局单例AndroidViewModelFactory,防止了每次创建工厂,优化了性能。
defaultFactory方法为获取默认工厂,如果ViewModelStoreOwner子类也实现了HasDefaultViewModelProviderFactory,则用其提供的工厂,否则用NewInstanceFactory工厂(创建无参ViewModel)。
HasDefaultViewModelProviderFactory
HasDefaultViewModelProviderFactory类
public interface HasDefaultViewModelProviderFactory {
// 获取默认Factory
@NonNull
ViewModelProvider.Factory getDefaultViewModelProviderFactory();
}
HasDefaultViewModelProviderFactory为标记可以获取到默认Factory。androidx的Activity和Fragment都已经实现了HasDefaultViewModelProviderFactory,我们来分别看一下它们的具体实现。
Activity
androidx.activity.ComponentActivity类
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
HasDefaultViewModelProviderFactory,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
ActivityResultCaller {
private ViewModelProvider.Factory mDefaultFactory;
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (getApplication() == null) {
// 不能在onCreate调用之前获取ViewModel
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
if (mDefaultFactory == null) {
// 默认工厂为空,则进行创建SavedStateViewModelFactory,会把Application、当前页面传入的参数,传入到构造方法中。
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
}
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 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
mDefaultFactory = new SavedStateViewModelFactory(
application,
this,
getArguments());
}
return mDefaultFactory;
}
}
androidx的Activity和Fragment的实现相同,都是创建SavedStateViewModelFactory并会把Application、当前页面传入的参数,传入到构造方法中,我们来看一下SavedStateViewModelFactory。
SavedStateViewModelFactory
SavedStateViewModelFactory类
public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
private final Application mApplication;
private final ViewModelProvider.Factory mFactory;
private final Bundle mDefaultArgs;
private final Lifecycle mLifecycle;
private final SavedStateRegistry mSavedStateRegistry;
// 构造方法,未传默认参数
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner) {
this(application, owner, null);
}
// 构造方法,传了默认参数
@SuppressLint("LambdaLast")
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
mFactory = application != null
? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
: ViewModelProvider.NewInstanceFactory.getInstance();
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
// 是否是AndroidViewModel子类
boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
Constructor<T> constructor;
if (isAndroidViewModel && mApplication != null) {
// 是AndroidViewModel子类,获取(Application, SavedStateHandle)签名的构造方法
constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
} else {
// 不是AndroidViewModel子类,获取(SavedStateHandle)签名的构造方法
constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
}
if (constructor == null) {
// 没有获取到,则说明是没用SavedStateHandle的构造方法,则直接用mFactory处理。
return mFactory.create(modelClass);
}
// 以下为需要SavedStateHandle
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
try {
T viewmodel;
if (isAndroidViewModel && mApplication != null) {
// 反射创建(Application, SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
viewmodel = constructor.newInstance(mApplication, controller.getHandle());
} else {
// 反射创建(SavedStateHandle)签名的构造方法,并传入SavedStateHandle。
viewmodel = constructor.newInstance(controller.getHandle());
}
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
// 返回ViewModel
return viewmodel;
} catch (IllegalAccessException e) {
throw new RuntimeException("Failed to access " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
} catch (InvocationTargetException e) {
throw new RuntimeException("An exception happened in constructor of "
+ modelClass, e.getCause());
}
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
// 使用类名作为key,创建ViewModemLastNonConfigurationInstancesl。
return create(canonicalName, modelClass);
}
// (Application, SavedStateHandle)签名
private static final Class<?>[] ANDROID_VIEWMODEL_SIGNATURE = new Class[]{Application.class,
SavedStateHandle.class};
// (SavedStateHandle)签名
private static final Class<?>[] VIEWMODEL_SIGNATURE = new Class[]{SavedStateHandle.class};
// 找到对应签名的构造方法,没有返回null。
@SuppressWarnings("unchecked")
private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
Class<?>[] signature) {
for (Constructor<?> constructor : modelClass.getConstructors()) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
if (Arrays.equals(signature, parameterTypes)) {
return (Constructor<T>) constructor;
}
}
return null;
}
/**
* @hide
*/
@Override
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void onRequery(@NonNull ViewModel viewModel) {
attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
}
}
androidx的Activity和Fragment创建默认工厂的代码流程:
androidx的Activity和Fragment创建SavedStateViewModelFactory时,都传入了Application,所以其工厂mFactory为AndroidViewModelFactory。create(String,Class<*>)方法,如果ViewModel构造方法里面没有用SavedStateHandle,则直接使用工厂mFactory(为AndroidViewModelFactory)进行创建。
说明:
- 使用
SavedStateViewModelFactory创建,如果此ViewModel构造方法里面没有用SavedStateHandle,则直接使用AndroidViewModelFactory创建;如果使用了,则反射创建(Application, SavedStateHandle)或(SavedStateHandle)签名的构造方法。
- 可以处理如下
ViewModel:
class MyViewModel : ViewModel()
class MyViewModel(application: Application) : AndroidViewModel(application)
class MyViewModel(val handle: SavedStateHandle) : ViewModel()
class MyViewModel(application: Application, val handle: SavedStateHandle) : AndroidViewModel(application)
- 由于
SavedStateHandle的创建,传入了当前页面传入的参数,所以通过SavedStateHandle也能获取到当前页面传入的参数。- 使用
SavedStateHandle相关的,将在Jetpact-保存状态讲解。
说完了ViewModelProvider对象的创建,我们再来看看其get()方法是如果获取ViewModel的。
ViewModelProvider.get方法
ViewModelProvider--> get方法
@MainThread
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")
// 使用默认名+类名作为key,获取ViewModel。
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
@Suppress("UNCHECKED_CAST")
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
// 从ViewModelStore中获取ViewModel
var viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
// viewModel不为空,并且是目标类,直接返回。
(factory as? OnRequeryFactory)?.onRequery(viewModel)
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody")
if (viewModel != null) {
// TODO: log a warning.
}
}
// 没有找到ViewModel,则直接创建,并存入到ViewModelStore中。
viewModel = if (factory is KeyedFactory) {
// 是KeyedFactory的子类直接调用create(key, modelClass)方法。
factory.create(key, modelClass)
} else {
factory.create(modelClass)
}
// 存入到ViewModelStore中
store.put(key, viewModel)
return viewModel
}
ViewModelProvider.get代码流程:
get(Class<*>)方法,使用默认名+类名作为key,调用get(String, Class<*>)方法,获取ViewModel。get(String, Class<*>)方法,先从ViewModelStore中获取ViewModel,如果有并且是目标类,则直接返回,否则使用Factory直接创建,并存入到ViewModelStore中,以便后续获取。
总结
以在androidx的Activity内获取无参构造方法ViewModel为例,讲解代码流程。
声明ViewModel
class MyViewModel : ViewModel() {
override fun onCleared() {
super.onCleared()
}
}
获取ViewModel
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 获取ViewModel
val model = ViewModelProvider(this).get(MyViewModel::class.java)
}
}
示例代码流程:
- 创建
ViewModelProvider,传入的是ComponentActivity,它的ViewModelStore为ComponentActivity提供的ViewModelStore,它的Factory为ComponentActivity提供的默认工厂SavedStateViewModelFactory。get()方法,先从ViewModelStore中获取ViewModel,如果有并且是目标类,则直接返回,否则使用Factory(SavedStateViewModelFactory)直接创建,并存入到ViewModelStore中,以便后续获取。SavedStateViewModelFactory的create()方法,会直接调用AndroidViewModelFactory的create()方法。(因为获取的MyViewModel未使用SavedStateHandle,所以会直接调用mFactory的创建。又因为创建SavedStateViewModelFactory时传入了Application,所以mFactory为AndroidViewModelFactory)AndroidViewModelFactory的create()方法,会直接使用反射创建无参构造方法。(因为获取的MyViewModel未继承AndroidViewModel,所以会走父类NewInstanceFactory的逻辑创建)
ViewModel生命周期
ViewModel生命周期为什么会比Activity、Fragment的生命周期长,它是如何保持不变的,以及它是如何被清除的,我们来分别分析以下。
ViewModel是如何保持不变的?
Activity和Fragment在配置变更(如:屏幕旋转)的情况会销毁并重新创建,但是再次获取的ViewModel实例不变。反向分析其原因,要想要ViewModel实例不变,则需要保持ViewModelStore不变。我们分别看一下androidx的Activity和Fragment的getViewModelStore()方法。
Activity
ComponentActivity--> getViewModelStore方法
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
// 不能在onCreate调用之前获取ViewModel
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
// 确保ViewModelStore
ensureViewModelStore();
// 返回ViewModelStore
return mViewModelStore;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// 从 NonConfigurationInstances 中恢复ViewModelStore
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
// mViewModelStore为空,则创建。
mViewModelStore = new ViewModelStore();
}
}
}
获取ViewModelStore,我们先从NonConfigurationInstances中获取,其内部包含了一个ViewModelStore成员变量,我们先来分析一下NonConfigurationInstances.viewModelStore是如何被赋值的,然后再来分析又是如何获取到它的。
说明:
- 为什么
ComponentActivity的mViewModelStore属性,在配置变更之前存入值,而在配置变更之后为空?
- 因为
Activity在配置变更之后,重新创建的Activity,Activity对象为新的,所以其mViewModelStore属性为初始状态:空。
ComponentActivity.NonConfigurationInstances类
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
通过查找引用,NonConfigurationInstances.viewModelStore是在ComponentActivity的onRetainNonConfigurationInstance()方法里完成赋值的。
ComponentActivity--> onRetainNonConfigurationInstance方法
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// viewModelStore为空,则说明此时没有调用过getViewModelStore(),则通过getLastNonConfigurationInstance()从重建之前的获取。
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
// 记录当前viewModelStore,完成赋值操作。
nci.viewModelStore = viewModelStore;
return nci;
}
此方法,创建ComponentActivity.NonConfigurationInstances对象,记录当前viewModelStore,并返回此对象。
说明:
- 重写了父类
Activity的onRetainNonConfigurationInstance()方法,使其创建的ComponentActivity.NonConfigurationInstances对象,在配置变更之后不受影响。ComponentActivity.NonConfigurationInstances.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore。
通过查找引用,ComponentActivity.onRetainNonConfigurationInstance()方法是在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();
// 记录当前activity数据,完成赋值操作。
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
此方法,创建Activity.NonConfigurationInstances对象,记录其activity要保存数据(即ComponentActivity.NonConfigurationInstances对象),并返回此对象。
说明:
Activity的retainNonConfigurationInstances()方法,使其创建的Activity.NonConfigurationInstances对象,在配置变更之后不受影响。Activity.NonConfigurationInstances.activity属性,保存了ComponentActivity.NonConfigurationInstances对象。
通过全局搜索,Activity.retainNonConfigurationInstances()方法是在ActivityThread的performDestroyActivity()方法里调用的。
ActivityThread--> performDestroyActivity方法
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
...
if (getNonConfigInstance) {
try {
// 从ActivityClientRecord的Activity中获取Activity.NonConfigurationInstances对象,
// 然后保存到它的lastNonConfigurationInstances中,完成保存操作。
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException("Unable to retain activity "
+ r.intent.getComponent().toShortString() + ": " + e.toString(), e);
}
}
}
...
// 回调Activity的onDestroy方法
mInstrumentation.callActivityOnDestroy(r.activity);
...
}
在Activity执行销毁的时候,会先将不会因配置变更而改变的数据(即Activity.NonConfigurationInstances)保存到ActivityClientRecord的lastNonConfigurationInstances属性中。
说明:
ActivityThread:它管理应用程序进程中主线程的执行、调度和执行activity、广播以及activity manager请求的其它操作。ActivityClientRecord:Activity客户端记录,用于真实的Activity实例的簿记。ActivityClientRecord.lastNonConfigurationInstances.activity.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore。
接下来,我们来看一下是如果获取到保存了在配置变更之前维护的ViewModelStore的,我们先来看一下Activity.getLastNonConfigurationInstance()方法。
Activity--> getLastNonConfigurationInstance方法
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
mLastNonConfigurationInstances为Activity.NonConfigurationInstances,getLastNonConfigurationInstance() 结果返回的是其activity属性,即ComponentActivity.NonConfigurationInstances对象。
我们再来看一下,mLastNonConfigurationInstances是在哪里进行赋值的。通过查找,mLastNonConfigurationInstances是在Activity的attach()里赋值的。
Activity--> attach方法
@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) {
...
// 完成赋值操作
mLastNonConfigurationInstances = lastNonConfigurationInstances;
...
}
通过全局搜索,Activity.retainNonConfigurationInstances()方法是在ActivityThread的performDestroyActivity()方法里调用的。
ActivityThread--> performLaunchActivity方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
// 调用attach,传入ActivityClientRecord的lastNonConfigurationInstances。
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.configCallback,
r.assistToken, r.shareableActivityToken);
...
return activity;
}
在Activity执行启动的时候,会调用其attach()方法,传入ActivityClientRecord.lastNonConfigurationInstances保存的Activity.NonConfigurationInstances对象。
说明:
- 为什么
ActivityThread的performLaunchActivity()、performDestroyActivity()方法里面ActivityClientRecord是同一个?
- 因为
ActivityClientRecord保存在了ActivityThread.mActivities属性中,其为ActivityClientRecord的Map集合,ActivityClientRecord在startActivityNow()方法内创建,并调用performLaunchActivity()方法,在其内部保存了创建的ActivityClientRecord对象,所以之后也能从Map中获取到之前存入的ActivityClientRecord,所以performLaunchActivity()、performDestroyActivity()方法里面ActivityClientRecord是同一个。
代码流程:
- 在
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.NonConfigurationInstances.viewModelStore属性的值,即可拿到ComponentActivity的ViewModelStore对象。
总结:
- 在
Activity销毁的时候,ActivityClientRecord.lastNonConfigurationInstances.activity.viewModelStore属性,保存了在配置变更之前维护的ViewModelStore。- 在
Activity启动的时候,ActivityClientRecord.lastNonConfigurationInstances的值在Activity.attach()的时候被存入到了Activity中,所以后续也能获取到在配置变更之前维护的ViewModelStore,所以配置变更前后获取到的ViewModelStore、ViewModel实例不变。
Fragment
@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方法会在Fragment的attach的时候调用,其中host为FragmentActivity的内部类FragmentActivity.HostCallbacks,它实现了ViewModelStoreOwner接口。
创建mNonConfig,如果没有父Fragment,则会从host中调用getViewModelStore()方法获取ViewModelStore,然后调用FragmentManagerViewModel.getInstance(viewModelStore)进行获取FragmentManagerViewModel。
因为一般没有父Fragment,大部分走第二个if,所以我们先来分析它,我们先来看一下FragmentActivity.HostCallbacks的getViewModelStore()方法,然后再来看一下FragmentManagerViewModel的getInstance()方法。
FragmentActivity.HostCallbacks --> getViewModelStore方法
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
ViewModelStoreOwner,
OnBackPressedDispatcherOwner,
ActivityResultRegistryOwner,
SavedStateRegistryOwner,
FragmentOnAttachListener {
...
@NonNull
@Override
public ViewModelStore getViewModelStore() {
return FragmentActivity.this.getViewModelStore();
}
...
}
FragmentActivity.HostCallbacks的getViewModelStore()方法,直接调用了FragmentActivity的getViewModelStore()方法,即调用了其父类ComponentActivity的getViewModelStore()方法。
所以FragmentManager.attachController()方法内,通过host也能获取到ComponentActivity的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。
说明:
- 传入的
ViewModelStore为ComponentActivity的ViewModelStore,一开始ViewModelStore内是没有FragmentManagerViewModel的,所以创建FragmentManagerViewModel并存入其ComponentActivity的ViewModelStore中。- 由于
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为ViewModelStore的Map集合。
说明:
- 为什么
FragmentManagerViewModel.getViewModelStore(Fragment)方法,要传入Fragment才能获取到ViewModelStore?
- 因为
FragmentManagerViewModel,保存到了ComponentActivity的ViewModelStore中,所以每个Fragment获取到的FragmentManagerViewModel实例相同,所以需要传入Fragment实例区分是获取ViewModelStore集合的哪个。
- 为什么
Fragment在配置变更前后获取到的ViewModelStore、ViewModel实例不变?
- 因为
ComponentActivity在配置变更前后获取到的ViewModelStore、ViewModel实例不变,所以存在ComponentActivity的ViewModelStore中的FragmentManagerViewModel实例不变,所以存在mViewModelStores的各个Fragment的ViewModelStore实例不变,所以ViewModel实例不变。
代码流程:
Fragment的attach的时候,获取到了ComponentActivity的ViewModelStore,创建FragmentManagerViewModel并存入到ComponentActivity的ViewModelStore中。FragmentManagerViewModel.getViewModelStore(Fragment)方法,通过Fragment从mViewModelStores中获取到对应的ViewModelStore,如果没有则进行创建后保存到mViewModelStores中。
ViewModel是如何被清除的?
要想分析ViewModel是如何被清除的,则需要分析ViewModelStore是如何被清除的。
Activity
通过引用查找,我们发现在ComponentActivity的构造方法里面调用了ViewModelStore的清除操作。
ComponentActivity类
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
//noinspection ConstantConditions
if (lifecycle == null) {
throw new IllegalStateException("getLifecycle() returned null in ComponentActivity's "
+ "constructor. Please make sure you are lazily constructing your Lifecycle "
+ "in the first call to getLifecycle() rather than relying on field "
+ "initialization.");
}
...
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
// 不是配置变更,清除全部ViewModel。
getViewModelStore().clear();
}
}
}
});
...
}
使用Lifecycle观察当前生命周期的状态,如果事件处于ON_DESTROY并且不是配置变更,则清空全部ViewModel。
说明:
Activity的ViewModel是如何被清除的?
- 使用
Lifecycle观察当前生命周期的状态,如果事件处于ON_DESTROY并且不是配置变更,则清空全部ViewModel。
Fragment
通过引用查找,我们发现在FragmentManagerViewModel的clearNonConfigStateInternal方法里面调用了ViewModelStore的清除操作。
FragmentManagerViewModel --> clearNonConfigStateInternal方法
void clearNonConfigState(@NonNull Fragment f) {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Clearing non-config state for " + f);
}
clearNonConfigStateInternal(f.mWho);
}
void clearNonConfigState(@NonNull String who) {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Clearing non-config state for saved state of Fragment " + who);
}
clearNonConfigStateInternal(who);
}
private void clearNonConfigStateInternal(@NonNull String who) {
// Clear and remove the Fragment's child non config state
FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(who);
if (childNonConfig != null) {
childNonConfig.onCleared();
mChildNonConfigs.remove(who);
}
// Clear and remove the Fragment's ViewModelStore
// 获取到对应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(Fragment)、clearNonConfigState(String)方法调用,然后它两又被几处调用,最后通过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(Fragment),清除不会因配置变更而改变的状态。
mFragmentStore.getNonConfig().clearNonConfigState(mFragment);
}
...
}
...
}
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)方法,会获取到对应Fragment的ViewModelStore,然后调用其clear()方法清除全部ViewModel。
说明:
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。
总结
以上就是全面的Jetpack-ViewModel源码了!之后会出Jetpack其它源码系列,请及时关注。如果你有什么问题,大家评论区见!
最后推荐一下我的网站,开发者的技术博客: devbolg.cn ,目前包含android相关的技术,之后会面向全部开发者,欢迎大家来体验!