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