ViewModel分析

发布时间:2024年01月15日
MainViewModel mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);

MainViewModel mainViewModel = new ViewModelProvider(getActivity()).get(MainViewModel.class);

上面两行代码中,第一行的“this” 关键字,既可以指代Activity本身,也可以指代Fragment本身。上第二行的“getActivity()”,则只能是指代Fragment的宿主Activity。

因此,Fragment之间的通信,我们可以通过这个上面第二行的方式,通过要通信的几个Fragment及宿主Activity共同创建一个ViewModel对象,在ViewModel对象中实现跨Fragment+Activity通信。

创建一个ViewModel,为什么在Activity/Fragment意外销毁(如旋转屏幕,黑白夜模式切换,语音言换)后,重启,ViewModel还存在,且与之前一样,没发生变化?

????public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
????????// 在 Activity/Fragment中,实现的都是 ViewModelStoreOwner 接口,因此,在Activity/Fragment创建 ViewModel 对象时,
????????// 下面 this()方法的第二个参数 对应的三目运算,通常会执行 后面的部分:NewInstanceFactory.getInstance()。
????????this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
????????????????? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
????????????????: NewInstanceFactory.getInstance());
????}

最后调用到这里:

    public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
????????mFactory = factory;
????????mViewModelStore = store;
????} ???

其中 mFactory 和 mViewModelStore定义如下:

private final Factory mFactory;
private final ViewModelStore mViewModelStore;

Factory是一个接口,轻定义如下:

    public interface Factory {
????????@NonNull
????????<T extends ViewModel> T create(@NonNull Class<T> modelClass);
????} ???

ViewModelStore 定义如下: ???

public class ViewModelStore {
????private final HashMap<String, ViewModel> mMap = new HashMap<>();
????// 执行put方法时,会判断 传入的“key”是否存在对应的 ViewModel 对象,如果存在,则执行 onCleared()方法。
????// 当然 ViewModel 的 onCleared()方法是一个空实现,具体的逻辑需要开发者自己去实现。
????final void put(String key, ViewModel viewModel) {
????????ViewModel oldViewModel = mMap.put(key, viewModel);
????????if (oldViewModel != null) {
????????????oldViewModel.onCleared();
????????}
????}
????// 根据 传进来的key,获取对应的 ViewModel 对象。当 Activity/Fragment意外销毁时,ViewModelStore对象还是存在的,并没有随之销毁。
????// 因此 Activity/Fragment 重建后,会调用该 get()方法重新获取到 ViewModel 对象。
????final ViewModel get(String key) {
????????return mMap.get(key);
????}
????Set<String> keys() {
????????return new HashSet<>(mMap.keySet());
????}
????// 当 应用被销毁时,会调用 该方法,清空所有的 ViewModel 对象:
????public final void clear() {
????????for (ViewModel vm : mMap.values()) {
????????????vm.clear();
????????}
????????mMap.clear();
????}
} ???

onCleared()方法实现如下: ???

????protected void onCleared() {

????} ???

ViewModel的 clear()方法实现如下:

    @MainThread
????final void clear() {
????????mCleared = true;
????????if (mBagOfTags != null) {
????????????synchronized (mBagOfTags) {
????????????????for (Object value : mBagOfTags.values()) {
????????????????????closeWithRuntimeException(value);
????????????????}
????????????}
????????}
????????onCleared();
????} ??

首先,我们要主要到该方法的注解:@MainThread,表明该方法只能是在主线程里面执行。

其次,mBagOfTags 定义如下:

????@Nullable
????private final Map<String, Object> mBagOfTags = new HashMap<>();

因此,mBagOfTags一定不为空,上面clear()方法的if(){...}判断会执行。 closeWithRuntimeException()方法实现如下: ?????

    private static void closeWithRuntimeException(Object obj) {
????????if (obj instanceof Closeable) {
????????????try {
????????????????((Closeable) obj).close();
????????????} catch (IOException e) {
????????????????throw new RuntimeException(e);
????????????}
????????}
????}

ViewModelStore的 clear()方法在 Activity的 onDestroy()方法中调用:

ComponentActivity.java中的调用如下:

????public ComponentActivity() {
????????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()) {
????????????????????????getViewModelStore().clear();
????????????????????}
????????????????}
????????????}
????????});
????}

ViewModelStore的 clear()方法在Fragment中,并不是由Fragment本身调用的,而是由 FragmentManagerViewModel.java调用的:????

    void clearNonConfigState(@NonNull Fragment f) {
????????if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
????????????Log.d(TAG, "Clearing non-config state for " + f);
????????}
????????// Clear and remove the Fragment's child non config state
????????FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
????????if (childNonConfig != null) {
????????????childNonConfig.onCleared();
????????????mChildNonConfigs.remove(f.mWho);
????????}
????????// Clear and remove the Fragment's ViewModelStore
????????ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
????????if (viewModelStore != null) {
????????????viewModelStore.clear();
????????????mViewModelStores.remove(f.mWho);
????????}
????}

或者在Jetpack组件中的 navigation 组件的 NavControllerViewModel.java 调用(NavControllerViewModel继承了ViewModel):???

?private final HashMap<UUID, ViewModelStore> mViewModelStores = new HashMap<>();
?    void clear(@NonNull UUID backStackEntryUUID) {
????????// Clear and remove the NavGraph's ViewModelStore
????????ViewModelStore viewModelStore = mViewModelStores.remove(backStackEntryUUID);
????????if (viewModelStore != null) {
????????????viewModelStore.clear();
????????}
????}


????@Override
????protected void onCleared() {
????????for (ViewModelStore store: mViewModelStores.values()) {
????????????store.clear();
????????}
????????mViewModelStores.clear();
????}

mViewModelStores变量保存ViewModelStore对象的put()方法:

????@NonNull
????ViewModelStore getViewModelStore(@NonNull UUID backStackEntryUUID) {
????????ViewModelStore viewModelStore = mViewModelStores.get(backStackEntryUUID);
????????if (viewModelStore == null) {
????????????viewModelStore = new ViewModelStore();
????????????mViewModelStores.put(backStackEntryUUID, viewModelStore);
????????}
????????return viewModelStore;
????}

该方法既执行了 mViewModelStores 的get()方法,也执行了 mViewModelStores 的put()方法。 ViewModelStore分析完,我们在回到 Factory 接口,在这里,他一共有两个 实现类:

抽象类 KeyedFactory 如下:????

    abstract static class KeyedFactory extends OnRequeryFactory implements Factory {
????????@NonNull
????????public abstract <T extends ViewModel> T create(@NonNull String key,
????????????????@NonNull Class<T> modelClass);

????????@NonNull
????????@Override
????????public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
????????????throw new UnsupportedOperationException("create(String, Class<?>) must "
????????????????????+ "be called on implementaions of KeyedFactory");
????????}
????}

实体类 NewInstanceFactory 如下:????

    public static class NewInstanceFactory implements Factory {
????????private static NewInstanceFactory sInstance;
????????// 该方法在 ViewModelProvider 的构造方法中被引用到,创建一个 NewInstanceFactory 对象
????????@NonNull
????????static NewInstanceFactory getInstance() {
????????????if (sInstance == null) {
????????????????sInstance = new NewInstanceFactory();
????????????}
????????????return sInstance;
????????}

????????@SuppressWarnings("ClassNewInstance")
????????@NonNull
????????@Override
????????public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
????????????try {
????????????????return modelClass.newInstance();
????????????} catch (InstantiationException e) {
????????????????throw new RuntimeException("Cannot create an instance of " + modelClass, e);
????????????} catch (IllegalAccessException e) {
????????????????throw new RuntimeException("Cannot create an instance of " + modelClass, e);
????????????}
????????}
????} ???

这两个 Factory 的子类,关键的都是 各自的create()方法,后面我还还会提到。

上面是 我们在创建 MainViewModel 对象时,第一步操作“new ViewModelProvider(this)”所看到的。

然后是 new ViewModelProvider(this).get(MainViewModel.class)后面的get()方法,他的实现如下:

????@NonNull
????@MainThread
????public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
????????// Class.getCanonicalName()返回的是 该类的 package包名 + 类名。不是全限定名。
????????String canonicalName = modelClass.getCanonicalName();
????????if (canonicalName == null) {
????????????throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
????????}
????????return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
????}

静态变量 DEFAULT_KEY定义如下:????

private static final String DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey";

因此,某个指定的 ViewModel所对应的key值“DEFAULT_KEY + ":" + canonicalName”,永远是不变的,相当于是final类型的。

然后get()方法调用到:????

    @NonNull
????@MainThread
????public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
????????// 从上面分析过的 mViewModelStore 对象中 的 mMap 变量中获取 key 值对应的 ViewModel对象
????????ViewModel viewModel = mViewModelStore.get(key);
????????// 如果我们传进来的 ViewModel 类与这里获取到的 ViewModel对象的类是同一个,就表明 我们所要创建 ViewModel的对象已经存在了会直接返回;
????????// 因此,当我们反复的调用 ViewModelProvider 去创建 ViewModel的对象 时,系统只会创建一次,之后世界从 mMap 中去获取,容纳后return返回。
????????if (modelClass.isInstance(viewModel)) {
????????????if (mFactory instanceof OnRequeryFactory) {
????????????????((OnRequeryFactory) mFactory).onRequery(viewModel);
????????????}
????????????return (T) viewModel;
????????} else {
????????????//noinspection StatementWithEmptyBody。这里看起来是执行了一个判空处理,其实是一个没什么实际意义的鸟代码。
????????????if (viewModel != null) {
????????????????// TODO: log a warning.
????????????}
????????}
????????// 如果我们在初始化 ViewModelProvider 时,传进来的 Factory 对象是 KeyedFactory 类型的,
????????// 那么久调用 KeyedFactory的 create()方法去创建一个 ViewModel 对象,并保存到 mMap中。
????????if (mFactory instanceof KeyedFactory) {
????????????viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
????????// 如果我们在初始化 ViewModelProvider 时,传进来的 Factory 对象是 NewInstanceFactory 类型的,
????????// 就调用 NewInstanceFactory 的 create()方法去创建一个 ViewModel 对象,并保存到 mMap中。
????????} else {
????????????viewModel = mFactory.create(modelClass);
????????}
????????// 最后是调用 put()方法,将创建的 ViewModel 对象保存到 mViewModelStore 对象中 的 mMap 变量中
????????mViewModelStore.put(key, viewModel);
????????return (T) viewModel; // 返回创建的 ViewModel 对象。
????}

NewInstanceFactory的create()方法如下: ??????????

    @SuppressWarnings("ClassNewInstance")
????@NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        try {
            // 起始就是通过反射创建对象。没什么可多说的。
            return modelClass.newInstance();
????????} catch (InstantiationException e) {
            throw new RuntimeException("Cannot create an instance of " + modelClass, e);
????????} catch (IllegalAccessException e) {
????????????throw new RuntimeException("Cannot create an instance of " + modelClass, e);
????????}
????}

文章来源:https://blog.csdn.net/haoyuegongzi/article/details/135596386
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。