ViewModel

1,052 阅读14分钟

1、ViewModel的获取

获取一个viewModel对象最基本的方法如下:

val viewModel = ViewModelProvider(owner).get(ActivityViewModel::class.java)

先看后面get方法:

internal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"

@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
    val canonicalName = modelClass.canonicalName
        ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
    return get("$DEFAULT_KEY:$canonicalName", modelClass)
}

传入class的canonicalName和DEFAULT_KEY拼接成一个字符串,然后传入get的重载方法中:

public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
    val viewModel = store[key]
    if (modelClass.isInstance(viewModel)) {
        (factory as? OnRequeryFactory)?.onRequery(viewModel!!)
        return viewModel as T
    } else {
        @Suppress("ControlFlowWithEmptyBody")
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    val extras = MutableCreationExtras(defaultCreationExtras)
    extras[VIEW_MODEL_KEY] = key
    // AGP has some desugaring issues associated with compileOnly dependencies so we need to
    // fall back to the other create method to keep from crashing.
    return try {
        factory.create(modelClass, extras)
    } catch (e: AbstractMethodError) {
        factory.create(modelClass)
    }.also { store.put(key, it) }
}

可以看到上面拼接的字符串是作为一个key,在store中获取该key对应的值(即viewModel对象)。如果获取到的值是传入的class的实例,就返回该对象,否则就通过factory创建一个对象返回,并将其存入store中。

2、ViewModel的存储

上面说了viewModel先从store中获取,说明store中存储着viewModel对象。那这个store是什么?这回再来看ViewModelProvider(owner):

public constructor(
    owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))

调用了重载构造方法:

constructor(
    private val store: ViewModelStore,
    private val factory: Factory,
    private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
) {...}

从这里可以看到store类型是ViewModelStore,是从ViewModelStoreOwner中得到的。

2.1. ViewModelStore

顾名思义它的作用是存储viewModel,这个类实现非常简单:

open class ViewModelStore {

    private val map = mutableMapOf<String, ViewModel>()

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    fun put(key: String, viewModel: ViewModel) {
        val oldViewModel = map.put(key, viewModel)
        oldViewModel?.onCleared()
    }

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    operator fun get(key: String): ViewModel? {
        return map[key]
    }

    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
    fun keys(): Set<String> {
        return HashSet(map.keys)
    }

    //清理所存储的所有viewModel
    fun clear() {
        for (vm in map.values) {
            vm.clear()
        }
        map.clear()
    }
}

里面仅有一个map字段用来存储viewModel,key就是上面提到的拼接的字符串,value就是viewModel对象。所以在不同的地方如果使用同一个ViewModelStore对象获取相同类型的ViewModel,那么得到的会是同一个对象。这也就是横竖屏切换viewModel能保存数据以及fragment与activity共享viewModel的原理。这个后面再说。

2.2. ViewModelStoreOwner

ViewModelStoreOwner也非常简单,是一个接口:

A scope that owns ViewModelStore.

interface ViewModelStoreOwner {
    val viewModelStore: ViewModelStore
}

很明显它的作用是返回ViewModelStore。ComponentActivityFragment类都实现了这个接口,所以在activity和fragment中创建ViewModelProvider可以直接传this。

看下它在ComponentActivity和Fragment类中的实现:

  • ComponentActivity中
private ViewModelStore mViewModelStore;
...
@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();  //确保mViewModelStore被实例化
    return mViewModelStore;
}

@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
    if (mViewModelStore == null) {
        //先看是不是activity异常销毁重建后需要恢复viewModel数据的情况,这个最后再分析
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        
        //如果不是需要恢复数据,就new出一个ViewModelStore对象。
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
}

ViewModelStore是直接放在Activity中的,正常情况下每个activity实例都有自己的ViewModelStore对象。

  • Fragment中

Fragment情况稍微复杂一点,ViewModelStore不是直接放在Fragment中,而是从FragmentManager中获取:

public ViewModelStore getViewModelStore() {
    if (mFragmentManager == null) {
        throw new IllegalStateException("Can't access ViewModels from detached fragment");
    }
    ...
    return mFragmentManager.getViewModelStore(this);
}

可以看到调用了FragmentManager的getViewModelStore方法,并把自身作为参数传入,继续跟进:

private FragmentManagerViewModel mNonConfig;
...
ViewModelStore getViewModelStore(@NonNull Fragment f) {
    return mNonConfig.getViewModelStore(f);
}

在FragmentManager中又是直接调用了mNonConfig的getViewModelStore方法,这个mNonConfig是FragmentManager中的一个变量,类型是FragmentManagerViewModel(FragmentManagerViewModel本身也是一个ViewModel,它也是被存储在一个ViewModelStore中的,这个稍后分析),继续跟进:

private final HashMap<String, ViewModelStore> mViewModelStores = new HashMap<>();
...
ViewModelStore getViewModelStore(@NonNull Fragment f) {
    ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
    if (viewModelStore == null) {
        viewModelStore = new ViewModelStore();
        mViewModelStores.put(f.mWho, viewModelStore);
    }
    return viewModelStore;
}

可以看到很简单,FragmentManagerViewModel里有一个map,用来存储所有Fragment实例(用mWho字段代替实例,每个实例的mWho是唯一的)和其对应的ViewModelStore对象。获取某个Fragment的ViewModelStore就是从map里获取,如果没有就new一个出来并存入map中。所以也可以说每个Fragment实例都有自己的ViewModelStore对象。

2.3. FragmentManagerViewModel

刚才提到了FragmentManagerViewModel本身也是一个ViewModel,它也是被存储在一个ViewModelStore中的,那它是何时被创建的?存储在哪个ViewModelStore中?

在FragmentManager中搜索mNonConfig的赋值代码,在attachController方法中,结果如下:

void attachController(@NonNull FragmentHostCallback<?> host,
        @NonNull FragmentContainer container, @Nullable final Fragment parent) {
    mHost = host;
    mContainer = container;
    mParent = parent;
    ...
    // Get the FragmentManagerViewModel
    if (parent != null) {
        mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
    } else if (host instanceof ViewModelStoreOwner) {
        ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
        mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
    } else {
        mNonConfig = new FragmentManagerViewModel(false);
    }
    ...
}

可以看到mNonConfig的赋值与parent和host参数的值有关。这里为了不打断思路直接说结果,一般情况下parent为null,host实现了ViewModelStoreOwner接口,并且返回的ViewModelStore就是 FragmentManager所关联的Activity的ViewModelStore。所以走的是mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore)。看一下FragmentManagerViewModel.getInstance(viewModelStore)方法:

static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
    ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore,
            FACTORY);
    return viewModelProvider.get(FragmentManagerViewModel.class);
}

很简单了,就是使用ViewModelProvider来获取ViewModel,传入viewModelStore,也就是Activity的viewModelStore,所以FragmentManagerViewModel是存储在FragmentManager所关联的Activity的ViewModelStore中,可以说是与Activity的业务ViewModel处于并列地位

  • 下面来分析一下parent和host

这两个是attachController方法的参数,所以要看attachController方法调用处的传参。该方法不是在FragmentManager内部调用的,所以需要找在哪里用到了FragmentManager。我们一般是在Activity中使用getSupportFragmentManager方法获取FragmentManager,看一下这个方法:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
...
public FragmentManager getSupportFragmentManager() {
    return mFragments.getSupportFragmentManager();
}

可以看到FragmentManager不是直接放在Activity中的,是通过mFragments.getSupportFragmentManager方法获取的,这个mFragments是Activity的一个常量,类型是FragmentController,值是通过createController方法获取的,createController方法里面就是直接调用的构造方法。

FragmentActivity不会直接操作FragmentManager,是通过FragmentController来操作FragmentManager的,所以在FragmentActivity中没有FragmentManager。

再来看下mFragments.getSupportFragmentManager方法:

private final FragmentHostCallback<?> mHost;
@NonNull
public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
    return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
}

private FragmentController(FragmentHostCallback<?> callbacks) {
    mHost = callbacks;
}

@NonNull
public FragmentManager getSupportFragmentManager() {
    return mHost.mFragmentManager;
}

FragmentManager依然不是放在FragmentController中的,返回的是mHost中的字段:

public abstract class FragmentHostCallback<E> extends FragmentContainer {
    ...
    final FragmentManager mFragmentManager = new FragmentManagerImpl();
    ....
}

所以 FragmentManager最终是放在FragmentHostCallback中的,并且每个Activity对象对应一个FragmentManager

在FragmentActivity、FragmentController、FragmentHostCallback中搜索FragmentManager的attachController方法,发现是在FragmentController中调用的:

public void attachHost(@Nullable Fragment parent) {
    mHost.mFragmentManager.attachController(
            mHost, mHost /*container*/, parent);
}

可以看到attachController方法的host参数就是这里的mHost,而从上面的代码可知mHost是在构造方法中赋值的,所以它的值就是在FragmentActivity中获取FragmentController对象时传入的new HostCallbacks()。 看一下HostCallbacks类:

class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
        OnConfigurationChangedProvider,
        OnTrimMemoryProvider,
        OnMultiWindowModeChangedProvider,
        OnPictureInPictureModeChangedProvider,
        ViewModelStoreOwner,
        OnBackPressedDispatcherOwner,
        ActivityResultRegistryOwner,
        SavedStateRegistryOwner,
        FragmentOnAttachListener,
        MenuHost {
    ...
    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        return FragmentActivity.this.getViewModelStore();
    }

它是FragmentActivity中的一个内部类,继承自FragmentHostCallback,实现了ViewModelStoreOwner接口,并且getViewModelStore方法实现是直接返回的FragmentActivity的ViewModelStore

host参数分析完了,再来看parent参数。parent参数是由FragmentController的attachHost方法传入的,FragmentController是在FragmentActivity中的,在FragmentActivity中搜一下:

private void init() {
    ...
    addOnContextAvailableListener(context -> mFragments.attachHost(null /*parent*/));
}

可以看到是在init方法中调用了mFragments.attachHost方法,传入的parent参数是null。

至此,经过上面的分析,可以得出最终结论:

Fragment的ViewModel存储在它对应的ViewModelStore中,ViewModelStore存储在FragmentManagerViewModel中的map中,而FragmentManagerViewModel存储在FragmentManager所关联的Activity的ViewModelStore中。

用一张图来说明:

image.png

3、viewModel的清除

1. ComponentActivity中

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();
                
                // isChangingConfigurations()方法返回值表示是否是配置变更销毁重建
                if (!isChangingConfigurations()) {
                    getViewModelStore().clear();
                }
            }
        }
    });
    ...
}

在无参构造方法中给lifecycle注册了观察者,在生命周期到达onDestroy时,如果activity是由于配置变化(即isChangingConfigurations()方法返回true)导致的销毁,就不清除,因为这种情况销毁后会重建,还需要使用到销毁前viewModel中的数据;如果是正常的结束销毁,就清除掉ViewModelStore中存储的viewModel对象。

isChangingConfigurations()方法:该方法返回的是Activity的mChangingConfigurations变量的值,该值正常情况下是false,当配置变更导致销毁重建时就被赋值为true。

这里提一句,可能在有些人的意识里ConfigurationChange就是屏幕旋转,这是不准确的,配置变化有很多种情况,比如语言地区变更、字体变更等等。只不过我们平时最常见到的配置变化就是屏幕旋转,其他的情况几乎遇不到。但这并不能把ConfigurationChange和屏幕旋转划等号。另外Activity有一个recreate方法,这个方法的作用就是销毁并重建,与配置发生变化时销毁重建的流程是一样的,所以调用这个方法导致activity销毁时也不会清理viewModelStore。

2. Fragment中

从上面的分析我们知道,Fragment的ViewModel最终实际也是存在activity的ViewModelStore中,所以在正常情况下,如果activity销毁了,会清理ViewModelStore,则依附于该activity的Fragment的ViewModel自然也被清理了。

4、Activity销毁重建时ViewModel不销毁原理

原理其实并不深奥,先用白话说一下根本原理:

ActivityThread先拿到销毁重建前的Activity实例的ViewModelStore对象,然后将其传递给重建后的Activity实例,这样重建前后的Activity的ViewModelStore是同一个对象,那里面的ViewModel自然也是相同的了。

下面结合源码分析一下。上面的小节中提到过了ViewModelStore初始化的代码:

void ensureViewModelStore() {
    if (mViewModelStore == null) {
        //先通过getLastNonConfigurationInstance方法获取NonConfigurationInstances,如果不为null,
        //说明是配置变更销毁重建,就从NonConfigurationInstances中获取ViewModelStore
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        
        //如果不是需要恢复数据,就new出一个ViewModelStore对象。
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
}

这个NonConfigurationInstances是ComponentActivity中的静态内部类(后续简称C_NCI),专门用于配置变更销毁重建时保存数据用。里面只有两个变量:

static final class NonConfigurationInstances {
    Object custom;
    ViewModelStore viewModelStore;
}

销毁前的activity实例的viewModelStore对象就是保存在这里,然后传递给重建后的activity实例。看下getLastNonConfigurationInstance方法,这个方法位于Activity中:

NonConfigurationInstances mLastNonConfigurationInstances;
...
public Object getLastNonConfigurationInstance() {
    return mLastNonConfigurationInstances != null
            ? mLastNonConfigurationInstances.activity : null;
}

返回的是mLastNonConfigurationInstances.activity。可以发现mLastNonConfigurationInstances的类型也是NonConfigurationInstances。但是要注意这个NonConfigurationInstances是Activity类的内部类(后续简称A_NCI),和刚才上面提到的C_NCI是不同的。看下A_NCI:

static final class NonConfigurationInstances {
    Object activity;
    HashMap<String, Object> children;
    FragmentManagerNonConfig fragments;
    ArrayMap<String, LoaderManager> loaders;
    VoiceInteractor voiceInteractor;
}

可以看到有个名为'activity'的变量(这个**命名真绝了),类型是Object。从上面的代码可知这个变量的值就是销毁前的acticity实例的C_NCI对象。那么关键就是找到这个变量的值是如何来的。

4.1.获取销毁前的activity实例的A_NCI对象

搜索一下mLastNonConfigurationInstances变量赋值的代码:

final void attach(...,NonConfigurationInstances lastNonConfigurationInstances,...) {
    ...
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    ...
}

可以看到是在attach方法中。attach方法我们知道是由系统的ActivityThread调用的,现在目光要进入ActivityThread中。

当一个activity实例需要销毁重建时,经过系统的一系列处理,会走到ActivityThread的handleRelaunchActivity方法:

public void handleRelaunchActivity(ActivityClientRecord tmp,
        PendingTransactionActions pendingActions) {
        //这里mActivities是一个HashMap,存储了当前存活的所有activity实例
        ActivityClientRecord r = mActivities.get(tmp.token);
        ...
        r.activity.mChangingConfigurations = true;
        handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
              pendingActions,tmp.startsNotResumed,tmp.overrideConfig,"handleRelaunchActivity");
        ...
}

ActivityClientRecord可以理解为Activity的容器类,里面除了存放activity实例,还有一些其他数据,其中就包括我们要找的A_NCI。每一个activity实例都会对应一个ActivityClientRecord实例。

参数tmp就是要销毁重建的activity实例对应的ActivityClientRecord,从mActivities中根据tmp的token获取到实际的activity实例,将mChangingConfigurations变量置为true(前面提到的isChangingConfigurations()方法返回的值就是在这里被置为true的),然后调用handleRelaunchActivityInner方法,将r传入(注意这个r,它是销毁前的activity实例,它后续会被传入到许多方法中)。点进handleRelaunchActivityInner方法:

private void handleRelaunchActivityInner(ActivityClientRecord r,...) {
    ...
    handleDestroyActivity(r, false, configChanges, true, reason);  //注意这里第四个参数传入了true
    ...
    handleLaunchActivity(r, pendingActions, customIntent);
}

可以看到先后调用了两个方法,从这里我们也可以得知Activity销毁重建过程的生命周期是先执行旧activity实例的onDestroy,再执行新activity实例的onCreate。点进handleDestroyActivity方法:

public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
        boolean getNonConfigInstance, String reason) {
    performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
    ...
}

调用了performDestroyActivity方法,继续跟进:

void performDestroyActivity(ActivityClientRecord r, boolean finishing,
        int configChanges, boolean getNonConfigInstance, String reason) {
    ...
    if (getNonConfigInstance) {  //从上面可知这个值传入的是true
        try {
            r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to retain activity "
                        + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
            }
        }
    }
    try {
        ...
        mInstrumentation.callActivityOnDestroy(r.activity);
        ...
    } catch (SuperNotCalledException e) {
        throw e;
    }
    ...

可以看到在这里将r中的lastNonConfigurationInstances变量赋值为当前activity(当前activity就是销毁前的实例)的retainNonConfigurationInstances方法返回的值。这个方法作用就是销毁重建时保存数据用。看下这个方法:

NonConfigurationInstances retainNonConfigurationInstances() {
    Object activity = onRetainNonConfigurationInstance();
    ...
    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.activity = activity;
    ...
    return nci;
}

注意这个方法是Activity类中的方法,返回的是A_NCI。在这个方法里new了一个A_NCI对象,将'activity'变量赋值为onRetainNonConfigurationInstance方法返回的值,然后将A_NCI对象返回。再看onRetainNonConfigurationInstance方法:

public Object onRetainNonConfigurationInstance() {
    return null;
}

发现直接返回的null。WTF??莫慌,这个方法在子类ComponentActivity中重写了。

另外之所以这个方法返回值(也即A_NCI中的activity变量)类型是Object,是为了兼容不同版本的实现,在不同版本的JDK或者不同的子类中可能实现保存数据功能的类型是不同的。

看下ComponentActivity中的这个方法:

public final Object onRetainNonConfigurationInstance() {
    ...
    ViewModelStore viewModelStore = mViewModelStore;
    ...
    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.viewModelStore = viewModelStore;
    return nci;
}

可以看到返回值类型是C_NCI,new了一个C_NCI对象返回了,并且将C_NCI对象中的viewModelStore变量赋值为当前activity实例的viewModelStore。至此ActivityThread就拿到了销毁前activity实例的A_NCI对象,A_NCI对象中存有C_NCI对象,C_NCI对象中存有当前activity实例的viewModelStore

4.2. 将销毁前的activity实例的A_NCI对象传递给重建后的activity实例

上一小节中分析了handleRelaunchActivityInner方法中的handleDestroyActivity方法,ActivityThread拿到了销毁前activity实例的A_NCI对象,下面来看如何传递给重建后的activity实例。看下handleLaunchActivity方法:

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    ...
    final Activity a = performLaunchActivity(r, customIntent);
    ...
}

调用了performLaunchActivity方法,跟进:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }

        if (activity != null) {
            ...
            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.activityConfigCallback,
                    r.assistToken, r.shareableActivityToken);
        }

关键就在这里,使用mInstrumentation.newActivity方法创建了一个新的activity实例,然后调用其attach方法,将r.lastNonConfigurationInstances(即销毁前的activity实例的A_NCI对象)传入,如此一来新activity实例中mLastNonConfigurationInstances变量的值就是旧activity实例的A_NCI对象,因此销毁重建时从新activity实例的C_NCI对象中获取到的viewModelStore就是旧activity实例的viewModelStore对象。至此activity销毁重建viewModel能保存数据的原理分析完毕。

5、总结

  1. viewModel对象是存储在ViewModelStore的map容器中,而每个Activity或Fragment(以下统称为owner)实例都有自己的ViewModelStore对象。每个owner实例可以有多个类型的ViewModel。

  2. Activity的ViewModelStore对象直接就是由Activity持有;Fragment的ViewModelStore对象是由FragmentManagerViewModel中的map持有,而FragmentManagerViewModel本身也是一个ViewModel,它存储在和它关联的Activity的ViewModelStore中,也就是说FragmentManagerViewModel与和它关联的Activity的业务ViewModel处于并列地位。

  3. 在不同的owner实例(注意是不同的实例,而不是不同的类型)中使用ViewModelProvider获取相同类型的ViewModel,得到的是不同的对象,因为不同的owner实例对应着不同的ViewModelStore对象。

  4. 要想Fragment共享Activity的ViewModel对象,就需要在Fragment中new ViewModelProvider时传入getActivity(),即它的宿主activity,这样ViewModelProvider拿到的ViewModelStore就是activity的store,获取到的viewModel就和activity的viewModel是同一个对象;同样如果要多个Fragment共享同一个ViewModel对象,也需要用getActivity()获取其宿主activity的ViewModelStore,这样获取到的才是同一个ViewModel对象。但是这里要注意,只有相同宿主activity下的多个Fragment可以共享同一个ViewModel对象,不同宿主activity下的Fragment用getActivity()获取到的ViewModel是不同的对象,所以不同宿主下的Fragment要想共享同一个ViewModel对象需要new ViewModelProvider时传入同一个自定义的ViewModelStore对象。