源码: Android API 29 查看顺序:AppCompatActivity—>FragmentActivity—>ComponentActivity
AppCompatActivity.java 同样的这里也只是委托了事件
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
getDelegate().onSaveInstanceState(outState);
}
FragmentActivity.java 中处理了数据的保存
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
markFragmentsCreated();
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mPendingFragmentActivityResults.size() > 0) {
outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);
int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
}
outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
}
}
ComponentActivity.java 的 onSaveInstanceState 方法中还是没有 ViewModel 的身影,但是紧接着的方法 onRetainNonConfigurationInstance 的注释有点意思,它是 final 所以不能重写,但是它里面又有一个公开的 onRetainCustomNonConfigurationInstance 方法,所以说我们可以重写该方法返回一些 Object 的对象,但是该方法过时了。
推荐我们使用 ViewModel 来实现。
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Lifecycle lifecycle = getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
}
super.onSaveInstanceState(outState);
mSavedStateRegistryController.performSave(outState);
}
/**
-
Retain all appropriate non-config state. You can NOT
-
override this yourself! Use a {@link androidx.lifecycle.ViewModel} if you want to
-
retain your own non config state.
*/
@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;
}
所以我们还是回到 ComponentActivity.java 的构造方法中找到 Lifecycle.Event.ON_DESTROY 的处理,
在里面有个方法 getViewModelStore 获取到了 ViewModel 的数据,它的实现如下:
@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.”);
}
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;
}
如果不使用 ViewModel
,在页面销毁和重建时可以用重写下面两个方法保存和恢复数据
-
onSaveInstanceState
-
onRestoreInstanceState
但是我们知道这两个方法只能保存 Bundle 支持的数据,要想保存其它数据就得用到下面的方法了
-
onRetainNonConfigurationInstance:final 所以不能重写,作用是保存数据,调用时机是
onStop()
和onDestroy()
之间 -
onRetainCustomNonConfigurationInstance:@Deprecated 过时了,推荐使用 ViewModel
-
getLastNonConfigurationInstance:作用是取出数据,调用时机是
onCreate()
之后 -
getLastCustomNonConfigurationInstance:@Deprecated 过时了,推荐使用 ViewModel
如果使用ViewModel
,在页面销毁和重建时就不需要你操心数据的保存和恢了。
ViewModel
会在onRetainNonConfigurationInstance
方法中保存数据,如下:
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;
}
}
如果Activity
重写了onRetainCustomNonConfigurationInstance
方法还可以将自定义的Object
类型的对象保存到NonConfigurationInstances 的 custom
属性中。如下:
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
并且还会在Activity
的onDestory
生命周期判断页面是否重建,重建则不删除ViewModel
中的数据
源码: Android API 29
首先我们要知道内存为何会泄漏。
短生命周期的对象被长生命周期的对象一直持有,导致短生命周期的对象在本该被回收的时候没有及时回收,导致内存泄漏。
比如:
内部类导致的内存泄漏如:非静态内部类 Handler、匿名内部类 Thread 中存在业务处理的时间比 Activity 的生命周期还长,这就会导致内存泄漏
因为内部类默认会持有外部类的引用,当外部类 Activity 关闭需要回收的时候,它的内部类还在持有它,导致它没有被回收。
在文章开头ViewModel
的使用中用到了LiveData
库。 它是具有生命感知的数据存储类,这种感知能力可确保 LiveData
仅更新处于活跃生命周期状态的应用组件观察者。
活跃生命周期状态也就是用户可见的状态下才会更新数据。详细的实现后面深入源码查看并写篇文章记录。
又因为ViewModel
会在onDestory
之后会自动清除相关数据,结合这两点即可避免内存泄漏。
(4) 如何在 Activity 中的两个或更多 Fragment 共享数据?
在创建 ViewModel 的时候需要传入this
上下文,这个上下文是个LifecycleOwner
, AppCompatActivity 和 Fragment
都默认实现了LifecycleOwner
接口,因此可以在Activity或者Fragment
中直接传递this
。
在传递上下文给 ViewModel
之后,会通过ViewModelStore
里面的HashMap
去根据不同的key
取出不同的ViewModel
, 而这里的 key
是androidx.lifecycle.ViewModelProvider.DefaultKey:
加上ViewModel
类所在的包含路径的全名称字符串。
而Activity
中的ViewModel
,除非被杀死或者关闭,否则一直存在。 这也就是为什么Activity
中的多个Fragment
能共享ViewModel
中的数据。
主要代码如下:
/**
-
Returns an existing ViewModel or creates a new one in the scope (usually, a fragment or
-
an activity), associated with this {@code ViewModelProvider}.
-
-
The created ViewModel is associated with the given scope and will be retained
-
as long as the scope is alive (e.g. if it is an activity, until it is
-
finished or process is killed).
-
@param key The key to use to identify the ViewModel.
-
@param modelClass The class of the ViewModel to create an instance of it if it is not
-
present.
-
@param The type parameter for the ViewModel.
-
@return A ViewModel that is an instance of the given type {@code T}.
*/
@NonNull
最后
由于文章篇幅原因,我只把面试题列了出来,详细的答案,我整理成了一份PDF文档,这份文档还包括了还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 ,帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习。
需要的朋友可以私信我【答案】或者点击这里免费领取