Jetpack之ViewModel源码解析

ViewModel是Jetpack框架集合中不可或缺的重要库之一,替我们管理着项目框架中的数据,相当于一个LiveData的数据总管一样。
它将视图与数据分离,对数据进行管理,当应用横竖屏切换时,不再需要考虑数据的存储与恢复。
ViewModel的源码分析主要分为两步:对象的创建和销毁。

一,ViewModel的创建过程

1,先创建一个ViewModel的类如下


class HomeViewModel : ViewModel() {

    private val _text = MutableLiveData<String>().apply {
        value = "This is home Fragment"
    }
    val text: LiveData<String> = _text
}

2,创建ViewModel对象

 val homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)

这是官方指定的一种创建方式,见源码
在这里插入图片描述
接下来就开始正在进入源码分析环节。
ViewModel对象的创建时,先创建了一个ViewModelProvider对象,并传入了当前上下文,然后再调用了它的get函数,传入了ViewModel的类
3,进入ViewModelProvider的构造函数,源码如下:


    /**
     * Creates {@code ViewModelProvider}. This will create {@code ViewModels}
     * and retain them in a store of the given {@code ViewModelStoreOwner}.
     * <p>
     * This method will use the
     * {@link HasDefaultViewModelProviderFactory#getDefaultViewModelProviderFactory() default factory}
     * if the owner implements {@link HasDefaultViewModelProviderFactory}. Otherwise, a
     * {@link NewInstanceFactory} will be used.
     */
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

根据源码可知,构造函数中传入了一个ViewModelStoreOwner对象,我们进入ViewModelStoreOwner文件,发现它是一个接口,如下:

public interface ViewModelStoreOwner {
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

既然创建时是在Activity中传入的this,那Activity肯定是实现了ViewModelStoreOwner接口,并实现了getViewModelStore函数。
4,进入ComponentActivity中,可以看到它实现了ViewModelStoreOwner接口

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        ContextAware,
        LifecycleOwner,
        //核心接口
        ViewModelStoreOwner,
      	//ViewModel的创建工厂接口
        HasDefaultViewModelProviderFactory,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner,
        ActivityResultRegistryOwner,
        ActivityResultCaller {
	
	......
}

在第三步中创建ViewModelProvider对象时会调用owner.getViewModelStore()函数,并判断owner 是否是 HasDefaultViewModelProviderFactory类型的。
5,进入getViewModelStore函数
它调用的是ComponentActivity的getViewModelStore中,发现它直接创建了一个ViewModelStore对象并返回

//此处省略若干行
...............
          @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        if (getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        ensureViewModelStore();
        return mViewModelStore;
    }

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void ensureViewModelStore() {
        if (mViewModelStore == null) {
        	//防止重复创建
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }

6,进入getDefaultViewModelProviderFactory函数,它创建了一个SavedStateViewModelFactory类型的对象并返回

    @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) {
            mDefaultFactory = new SavedStateViewModelFactory(
                    getApplication(),
                    this,
                    getIntent() != null ? getIntent().getExtras() : null);
        }
        return mDefaultFactory;
    }

7,ViewModelProvider的构造函数结束了,接下来就看一下get函数

   private static final String DEFAULT_KEY =
            "androidx.lifecycle.ViewModelProvider.DefaultKey";
    @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");
        }
        //使用了默认的一个字符串加上类名拼接出一个key
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    
  @NonNull
    @MainThread
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    	//从ViewModelStore中的HashMap中获取,防止重复创建
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
        	//根据ViewModelProvider的构造函数可知,此处的mFactory是SavedStateViewModelFactory类型的(OnRequeryFactory是SavedStateViewModelFactory的父类)
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        
        //SavedStateViewModelFactory继承KeyedFactory接口
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        //创建一个ViewModel对象,根据拼接的key存入ViewModelStore中的HashMap中
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

8,进入SavedStateViewModelFactory中的可知它继承自KeyedFactory,而KeyedFactory又继承了OnRequeryFactory,

public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {
}
 abstract static class KeyedFactory extends OnRequeryFactory implements Factory {
}

查看create函数发现它是通过反射的方式创建了一个ViewModel对象。

  @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 && mApplication != null) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        // doesn't need SavedStateHandle
        if (constructor == null) {
            return mFactory.create(modelClass);
        }

        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
            if (isAndroidViewModel && mApplication != null) {
                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());
        }
    }

到此ViewModel的创建就完成了,接下来看一下ViewModelStore,它的代码很简单就这么几十行,内部创建了一个HashMap,以ViewModelProvider中拼接的字符串key,保存我们创建的ViewModel对象。

public class ViewModelStore {

    private final HashMap<String, ViewModel> mMap = new HashMap<>();

    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();
    }
}

二,ViewModel的销毁

根据ViewModel的创建过程可知,ViewModel对象销毁是和ViewModelStore息息相关,而ViewModelStore的创建是在ComponentActivity中,所以销毁也必定在这里面,在ComponentActivity中的构造函数中,通过lifecycle监听页面的销毁。

     this.getLifecycle().addObserver(new LifecycleEventObserver() {
                public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
                    if (event == Event.ON_DESTROY) {
                        ComponentActivity.this.mContextAwareHelper.clearAvailableContext();
                        //判断Activity是否非正常销毁
                        if (!ComponentActivity.this.isChangingConfigurations()) {
                            //回收ViewModel,并触发onCleared
                            ComponentActivity.this.getViewModelStore().clear();
                        }
                    }
                }
            });

isChangingConfigurations 函数就是判断是否因屏幕旋转导致触发的生命周期,这也就是为什么屏幕旋转后ViewModel中LiveData保存的值不会丢失。
总结
ViewModel的创建使用了工厂模式,创建完成后存入到ViewModelStore(ViewModelStore对象的创建是在Activity中)中的HashMap,Key是通过ViewModel的类名+默认的字符串,Value则是当前存入的ViewModel对象,当Activity/Fragment正常销毁时,会调用ViewModelStore中的Clear函数遍历删除HashMap中存入的ViewModel对象,然后触发onCleared函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值