private val mViewModel: DataTestViewModel by viewModels()
可见viewModel的获取是通过viewModels代理类实现的,我们继续跟进
@MainThread inline fun <reified VM : ViewModel> ComponentActivity.viewModels( noinline factoryProducer: (() -> Factory)? = null ): Lazy<VM> { // 1 获取factoryPromise,默认为null,使用defaultViewModelProviderFactory val factoryPromise = factoryProducer ?: { defaultViewModelProviderFactory } // 2 通过 ViewModelLazy 获取ViewModel实例 return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise) }
@NonNull @Override public ViewModelProvider.Factory getDefaultViewModelProviderFactory() { if (getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); } if (mDefaultFactory == null) { // 创建defaultFactory mDefaultFactory = new SavedStateViewModelFactory( getApplication(), this, getIntent() != null ? getIntent().getExtras() : null); } return mDefaultFactory; }
构造传参数,通过工厂类SavedStateViewModelFactory创建ViewModelFactory类型实例作为mDefaultFactory
SavedStateViewModelFactory构造获取SavedStateViewModelFactory
@SuppressLint("LambdaLast") public SavedStateViewModelFactory(@NonNull Application application, @NonNull SavedStateRegistryOwner owner, @Nullable Bundle defaultArgs) { mSavedStateRegistry = owner.getSavedStateRegistry(); mLifecycle = owner.getLifecycle(); mDefaultArgs = defaultArgs; mApplication = application; mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); }
@NonNull @Override public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) { boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass); Constructor<T> constructor; if (isAndroidViewModel) { constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE); } else { constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE); } // doesn't need SavedStateHandle if (constructor == null) { // 通过mFactory直接创建viewModel return mFactory.create(modelClass); } SavedStateHandleController controller = SavedStateHandleController.create( mSavedStateRegistry, mLifecycle, key, mDefaultArgs); try { T viewmodel; if (isAndroidViewModel) { // 通过构造方法实例化viewModel viewmodel = constructor.newInstance(mApplication, controller.getHandle()); } else { viewmodel = constructor.newInstance(controller.getHandle()); } viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller); 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()); } }
通过create方法我们可以知道viewModel的创建有两种方式:
1、 通过mFactory.create(modelClass)方法获取
2、通过constructor.newInstance(mApplication, controller.getHandle())获取
class ViewModelLazy<VM : ViewModel> ( private val viewModelClass: KClass<VM>, // 1 viewModelStore获取 private val storeProducer: () -> ViewModelStore, // 2 factoryProducer获取 private val factoryProducer: () -> ViewModelProvider.Factory ) : Lazy<VM> { private var cached: VM? = null override val value: VM get() { val viewModel = cached return if (viewModel == null) { // 获取factory val factory = factoryProducer() // 获取store val store = storeProducer() // 3 通过ViewModelProvider传递参数factory和store获取viewmodel ViewModelProvider(store, factory).get(viewModelClass.java).also { // 缓存viwemodel cached = it } } else { viewModel } } override fun isInitialized() = cached != null }
/** * Returns the {@link ViewModelStore} associated with this activity * <p> * Overriding this method is no longer supported and this method will be made * <code>final</code> in a future version of ComponentActivity. * * @return a {@code ViewModelStore} * @throws IllegalStateException if called before the Activity is attached to the Application * instance i.e., before onCreate() */ @NonNull @Override public ViewModelStore getViewModelStore() { // application为空时,也就是在activity添加到应用之前,获取viewModelStore抛出异常 if (getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the " + "Application instance. You can't request ViewModel before onCreate call."); } if (mViewModelStore == null) { // 首先通过NonConfigurationInstances获取viewModelStore NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance(); if (nc != null) { // Restore the ViewModelStore from NonConfigurationInstances mViewModelStore = nc.viewModelStore; } // 1 通过NonConfigurationInstances获取viewModelStore失败,直接创建ViewModelStore if (mViewModelStore == null) { // 2 mViewModelStore = new ViewModelStore(); } } return mViewModelStore; }
@Nullable public Object getLastNonConfigurationInstance() { return mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.activity : null; }
那既然通过NonConfigurationInstances中viewModelStore可以获取viewModelStore,那么mLastNonConfigurationInstances是什么时候赋值的呢?我们继续跟进
通过跟进源码我们查看mLastNonConfigurationInstances赋值是通过Activity的attach方法进行的
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) { ... 省略非关联代码 mLastNonConfigurationInstances = lastNonConfigurationInstances;
继续跟进我们知道是从ActivityThread中performLaunchActivity方法中调用了activity的attach方法
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... 省略非关键代码 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);
通过代码我们发现lastNonConfigurationInstances赋值是通过ActivityClientRecord获取的
static final class NonConfigurationInstances { Object custom; ViewModelStore viewModelStore; }
public class ViewModelStore { // 内部map private final HashMap<String, ViewModel> mMap = new HashMap<>(); // 存储key,viewModel 键值 final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } } final ViewModel get(String key) { return mMap.get(key); } Set<String> keys() { return new HashSet<>(mMap.keySet()); } /** * Clears internal storage and notifies ViewModels that they are no longer used. */ public final void clear() { for (ViewModel vm : mMap.values()) { vm.clear(); } mMap.clear(); } }
@NonNull @MainThread public <T extends ViewModel> T get(@NonNull Class<T> modelClass) { String canonicalName = modelClass.getCanonicalName(); if (canonicalName == null) { throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels"); } // 1 return get(DEFAULT_KEY + ":" + canonicalName, modelClass); }
继续跟进 get方法
@SuppressWarnings("unchecked") @NonNull @MainThread public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) { // 通过mViewStore键查询获取viewModel ViewModel viewModel = mViewModelStore.get(key); if (modelClass.isInstance(viewModel)) { // OnRequeryFactory类型factory if (mFactory instanceof OnRequeryFactory) { ((OnRequeryFactory) mFactory).onRequery(viewModel); } // 直接返回viewModel return (T) viewModel; } else { //noinspection StatementWithEmptyBody if (viewModel != null) { // TODO: log a warning. } } // KeyedFactory类型 if (mFactory instanceof KeyedFactory) { viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass); } else { viewModel = (mFactory).create(modelClass); } // 存储 mViewModelStore.put(key, viewModel); return (T) viewModel; }
通过mViewModelStore的get的键查询viewModel实例,并根据传入的mFactory类型不同来做不同的处理
1、传入的modelClass是与viewModel实例相同,并且mFactory是OnRequeryFactory类型,通过查询的方式获取viewModel
2、传入的mFactory是KeyedFactory类型时,通过KeyedFactory的create方法创建viewModel
3、非上述两种factory时直接调用mFactory的create方法创建veiwModel
4、创建完成viewModel将viewModel存储到mViewModelStore中