基本使用:
class ChooseAreaViewModel :ViewModel(){
var provinceLiveData = MutableLiveData<MutableList<Province>>()
fun getProvinceList(){
viewModelScope.launch {
provinceLiveData.value = PlaceRepository.getProvinceList()
}
}
}
class MVVMActivity:AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_mvvm)
viewModel = ViewModelProviders.of(this).get(ChooseAreaViewModel::class.java)
viewModel.provinceLiveData.observe(this, Observer {result->
Log.e("TAG",result[0].provinceName)
Log.e("TAG",Thread.currentThread().name)
text.text = result[0].provinceName+result[0].code+result[0].provinceCode
})
}
}
源码解析
首先构建ViewModelProvider
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
//单例获取ViewModelFactory,后续会只用该类通过反射传建对应的viewModel
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
调用ViewModelProvider的get方法获取viewModel
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);
}
@NonNull
@MainThread
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;
}
public static class NewInstanceFactory implements Factory {
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
//反射创建viewModel实例
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);
}
}
}
从viewModelStore中获取viewModel,如果不存在则创建完成viewModel后添加到ViewModelStore里面的HashMap
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保存在viewModelStore中,而viewModel生命周期比activity长,
因此我们重点关注viewModelStore生命周期
获取ViewModelStore,首先从ComponentActivity类中调用getViewModelStore
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
LifecycleOwner,
ViewModelStoreOwner,
SavedStateRegistryOwner,
OnBackPressedDispatcherOwner {
@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.");
}
//判断该ComponentActivity中的mViewModelStore是否为空,activity初次创
次创建后为空,当屏幕旋转后不为空使用第一次创建的ViewModelStore
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;
}
//主要功能是把viewModelStore包装在NonConfigurationInstances类中
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
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;
}
}
由上面可知viewModelStore在activity初次创建时为空,当屏幕反转时使用第一次的viewModelStore,当屏幕反转时viewModelStore是如何保存的
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback,
AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
// We're already stopped but we've been asked to retain.
// Our fragments are taken care of but we need to mark the loaders for retention.
// In order to do this correctly we need to restart the loaders first before
// handing them off to the next activity.
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;
}
}
首先在activity类中调用retainNonConfigurationInstances()方法,在该方法中再次调用ComponentActivity的onRetainNonConfigurationInstance方法对viewModel进行包装,然后再retainNonConfigurationInstances方法中再次进行包装,接下来看activity类中etainNonConfigurationInstances()方法如何调用的
在ActivityThread类中当屏幕进行旋转会发送RELAUNCH_ACTIVITY信号,然后调用handleRelaunchActivityLocally方法,最终调用handleRelaunchActivity方法,具体可参考android activity详细启动调用
接下来看ActivityThread类中的handleRelaunchActivity方法
public void handleRelaunchActivity(ActivityClientRecord tmp,
PendingTransactionActions pendingActions) {
......
handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
.......
}
private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
........
handleDestroyActivity(r.token, false, configChanges, true, reason);
........
}
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance, reason);
........
handleLaunchActivity(r, pendingActions, customIntent);
}
/** Core implementation of activity destroy call. */
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = mActivities.get(token);
........
r.lastNonConfigurationInstances
= r.activity.retainNonConfigurationInstances();
........
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnDestroy(r.activity);
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + safeToComponentShortString(r.intent) +
" did not call through to super.onDestroy()");
}
if (r.window != null) {
r.window.closeAllPanels();
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to destroy activity " + safeToComponentShortString(r.intent)
+ ": " + e.toString(), e);
}
}
r.setState(ON_DESTROY);
......
}
可以看到通过一系列调用最终调用performDestroyActivity,该方法调用activity.retainNonConfigurationInstances后,把activity.retainNonConfigurationInstances中包装的viewModel保存在ActivityClientRecord的lastNonConfigurationInstances属性中,再调用mInstrumentation.callActivityOnDestroy(r.activity)方法通知activity调用onDestory方法
保存在ActivityClientRecord的lastNonConfigurationInstances属性,如何获取的呢,可以看到在handleDestroyActivity方法中调用performDestroyActivity方法后,最终会调用handleLaunchActivity方法
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
.......
final Activity a = performLaunchActivity(r, customIntent);
.......
}
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.......
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);
.......
}
可以看到在performLaunchActivity中会调用activity.attach方法,该方法中包含参数r.lastNonConfigurationInstances
总结:当activity首次创建时首先会new一个viewModelStore,然后经过一些列包装会把该viewModelStore保存在activity类中的NonConfigurationInstances的静态内部类中,然后再ActivityThread类中当收到屏幕反转的信号,最终调用performDestroyActivity方法,在该方法中把activity类中的NonConfigurationInstances保存在ActivityClientRecord的lastNonConfigurationInstances属性中,然后才会通知activity调用onDestory。
当上述保存操作执行后,会调用performLaunchActivity方法,该方法会调用activity.attach方法,传入上述保存的ActivityClientRecord的lastNonConfigurationInstances属性
当调用finish方法结束当前activity时由于不会触发activity.retainNonConfigurationInstances()方法,因此不会进行保存ViewModelStore,故需要清空ViewModelStore中保存的viewModel
public ComponentActivity() {
......
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
......
}
可以看到这里使用lifecycle进行监听,当页面onDestory时,如果不是有屏幕反转之类的导致的,那么将清空ViewModelStore中存储的viewModel