编程语言
首页 > 编程语言> > ViewModel源码分析

ViewModel源码分析

作者:互联网

Activity中ViewModel实例的获取
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)
}
1、ComponentActivity 中 getDefaultViewModelProviderFactory
 @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;
    }
  @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())获取

2、通过ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)构建ViewModel实例
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
}
2.1 viewModelStore的获取
  /**
     * 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();
    }
}
3、ViewModelProvider(store, factory).get(viewModelClass.java)方法
  @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中

4、流程图:

在这里插入图片描述

标签:分析,ViewModel,return,get,mFactory,viewModel,源码,modelClass,null
来源: https://blog.csdn.net/sinat_35241409/article/details/120569323