從API調用入手
創建ViewModel實例
//MainActivity
ViewModelProvider(this)[MainViewModel::class.java]
this--->MainActivity
Activity繼承關係:
MainActivity->AppCompatActivity->FragmentActivity->ComponentActivity
ComponentActivity實現ViewModelStoreOwner接口重寫getViewModelStore()方法
@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.");
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
ViewModelProvider(this)
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
ViewModelStoreOwner--->ComponentActivity
owner.getViewModelStore()--->ViewModelStore
ViewModelProvider.get()
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");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
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.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
ViewModelStore.get()
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());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
API調用流程總結:
ViewModelProvider(this)傳入ViewModelStoreOwner接口實現類ComponentActivity,ComponentActivity重寫了抽象方法getViewModelStore()返回ViewModelStore;
ViewModelProvider.get(ViewModel::class.java)通過ViewModelStore獲取ViewModel;
ViewModelStore內部維護了一個HashMap,key是ViewModel類名,value是ViewModel實例。
接下來看ViewModel核心功能,Activity重建恢復數據。
回到ComponentActivity.getViewModelStore()
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
nc不爲null,通過nc獲取viewModelStore
獲取nc--->getLastNonConfigurationInstance()
調用父類Activity.getLastNonConfigurationInstance()
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
找一下mLastNonConfigurationInstances賦值處
Activity.attach()
...
mLastNonConfigurationInstances = lastNonConfigurationInstances;
...
至於attach()方法調用處,前面很多篇都說過
ActivityThread.performLaunchActivity(ActivityClientRecord r...)
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中獲取
lastNonConfigurationInstances何時保存到ActivityClientRecord中的呢?
既然ViewModel在屏幕旋轉,Activity銷燬重建後可恢復數據,先找到Activity.Destroy()調用處
ActivityThread.performDestroyActivity()
ActivityClientRecord r = mActivities.get(token);
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
Activity.retainNonConfigurationInstances()
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
mFragments.doLoaderStart();
mFragments.doLoaderStop(true);
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
Object activity = onRetainNonConfigurationInstance()
調用子類ComponentActivity.onRetainNonConfigurationInstance()
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
nci.activity = activity
這裏activity其實是個Object對象也就是上述方法返回值:
ComponentActivity.NonConfigurationInstances
其內部保存ViewModelStore實例
回看Activity.getLastNonConfigurationInstance()
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
取保存的ComponentActivity.NonConfigurationInstances實例
流程很清晰了:
Activity.Destroy()時保存了ViewModelStore,在Activity啓動、實例化時調用Activity.attach()恢復。ViewModelStore內部維護HashMap存儲ViewModel實例。