hi,同学们大家好!
1、Configuration应用开发背景
今天要给大家分享内容就是我们应用开发时候经常会遇到问题,那就是如果系统一些属性变化了,比如语言,横竖屏幕,深色模式等。就会导致系统当前的TopActivity会进行destory后进行重新create情况。如果不想要reCreate Activity那么我们就需要到AndroidManifest中去声明对应的configChange,这个 时候就会让Activity不重新reCreate,即Activity可以不需要重建,但是Activity就会执行对应回调onConfigurationChanged。
入门课,实战课,跨进程专题,input专题
ps需要学习深入framework课程和课程优惠
新课程优惠获取请加入qq群:422901085
2、源码分析Activity的relaunch部分
这里 我们可以先分析Activity的reLaunch部分即Activity的重建
那怎么分析呢?
这里我们就以一些log线索来入手,因为大家知道源码分析的话因为源码太多,你得找到一个合适的切入点,不然确实分析源码基本等于大海捞针。
寻找切入点:
这里我们都是知道Activity重新创建会执行onDestroy,我们就在onDestroy进行堆栈拦截看看是哪里调用过来的。
这里很明显我们看出来了,其实是因为应用进程执行了ActivityRelaunchItem这个跨进程通信类,导致执行了对应的handleRelaunchActivityInner,再执行到handleDestroyActivity方法
那么这里其实 我们重点就应该放到具体服务端是哪里传递了ActivityRelaunchItem。
这里通过堆栈或者 调试方法 已经不起作用了,因为 是跨进程方式,当然无法追踪。
那就只能grep方式:
结果如下
明显我们就知道在ActivityRecord类中
这里调用其实是被 ensureActivityConfiguration调用的
具体调用栈:
这里就有个疑问了,config变化了难道就一定要进行relaunch么?这个就是我们接下来要分析的
onConfigurationChanged情况
3、源码分析非relaunch情况,执行onConfigurationChanged情况
前面我们已经知道config变化后就2种情况
1 Activity重启
2 Activity不进行重启,但要进行AndroidManifest的声明,然后会会回调onConfigurationChanged的方法
直接重启和Manifest中声明的差异到底在哪里呢?
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
boolean ignoreVisibility) {
if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
if (mState == PAUSING) {
deferRelaunchUntilPaused = true;
preserveWindowOnDeferredRelaunch = preserveWindow;
return true;
} else {
relaunchActivityLocked(preserveWindow);
}
return false;
}
if (displayChanged) {
scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
} else {
scheduleConfigurationChanged(newMergedOverrideConfig);
}
return true;
}
这里其实就可以看出来执行scheduleConfigurationChanged其实最后就会导致Activity的onConfigurationChanged的执行
但是前面shouldRelaunchLocked如果为true,那么就会导致Activity的重启
故问题关键变成了 shouldRelaunchLocked方法
private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
int configChanged = info.getRealConfigChanged();
boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
return (changes&(~configChanged)) != 0;
}
那么来看看info.getRealConfigChanged();具体实现情况:
public int getRealConfigChanged() {
return applicationInfo.targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB_MR2
? (configChanges | ActivityInfo.CONFIG_SCREEN_SIZE
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE)
: configChanges;
}
这里其实就是ActivityInfo类中的configChanges变量
那么configChanges变量又是哪来的呢?
其实在包解析时候就已经进行了获取
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)