窗口容器的Configuration介绍
这个问题也困扰我很久!很多configer 我一直也没管它,只是有时候遇到了 糊里糊涂的!!!
不过遇到一个MTBF set config重启问题 还是理了下,这里记录一下
先理一下到底是怎么回事吧
首先看看到底有哪些config吧
我们说WindowManager 大都结构都称之为容器的东西 这个容器的基类是ConfigurationContainer,这玩意本身是容器 同时他也是容器的容器!绕口燃石就是这个意思
所有的容器(不管是Task 还是activityRecord等)都继承于他
乱七八糟的各种config 实际上整理一下也就下面几个(我们之所以觉得多 是因为不清楚,清楚了其实也就不复杂了)
/**
- Contains requested override configuration settings applied to this configuration container.
*/
private Configuration mRequestedOverrideConfiguration = new Configuration();
/**
- Contains the requested override configuration with parent and policy constraints applied.
- This is the set of overrides that gets applied to the full and merged configurations.
*/
private Configuration mResolvedOverrideConfiguration = new Configuration();
/**
- Contains full configuration applied to this configuration container. Corresponds to full
- parent’s config with applied {@link #mResolvedOverrideConfiguration}.
*/
private Configuration mFullConfiguration = new Configuration();
/**
- Contains merged override configuration settings from the top of the hierarchy down to this
- particular instance. It is different from {@link #mFullConfiguration} because it starts from
- topmost container’s override config instead of global config.
*/
private Configuration mMergedOverrideConfiguration = new Configuration();
这几个config到底是什么意思呢?
首先看第一个mRequestedOverrideConfiguration
这个里面其实就是当前ConfigurationContainer 主动请求的所有config ,以nightmode 为例说明
app可以自己调用 setOverrideNightMode
public boolean setOverrideNightMode(int nightMode) {
final int currentUiMode = mRequestedOverrideConfiguration.uiMode;
final int currentNightMode = currentUiMode & Configuration.UI_MODE_NIGHT_MASK;
final int validNightMode = nightMode & Configuration.UI_MODE_NIGHT_MASK;
if (currentNightMode == validNightMode) {
return false;
}
mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
mRequestsTmpConfig.uiMode = validNightMode
| (currentUiMode & ~Configuration.UI_MODE_NIGHT_MASK);
onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
return true;
}
来改变自身NightMode 从而使应用和系统默认应用到所有app 不一样 可以理解为此为当前应用主动请求的所有config
mResolvedOverrideConfiguration 是个啥?
来看看mResolvedOverrideConfiguration的计算
默认mResolvedOverrideConfiguration 其实就等于mRequestedOverrideConfiguration
void resolveOverrideConfiguration(Configuration newParentConfig) {
mResolvedOverrideConfiguration.setTo(mRequestedOverrideConfiguration);
}
然后对于后面的子类 大都会重写一下resolveOverrideConfiguration
如:
DisplayArea.java
void resolveOverrideConfiguration(Configuration newParentConfiguration) {
super.resolveOverrideConfiguration(newParentConfiguration);
final Configuration resolvedConfig = getResolvedOverrideConfiguration();
final Rect overrideBounds = resolvedConfig.windowConfiguration.getBounds();
final Rect overrideAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
// If there is no override of appBounds, restrict appBounds to the override bounds.
if (!overrideBounds.isEmpty() && (overrideAppBounds == null || overrideAppBounds.isEmpty())
&& parentAppBounds != null && !parentAppBounds.isEmpty()) {
final Rect appBounds = new Rect(overrideBounds);
appBounds.intersect(parentAppBounds);
resolvedConfig.windowConfiguration.setAppBounds(appBounds);
}
}
会对mResolvedOverrideConfiguration的AppBounds根据自身规则进行调整一下
所以可以理解为mResolvedOverrideConfiguration 为mRequestedOverrideConfiguration 经过子类的的调整后的对应容器请求的config
mFullConfiguration 又是什么呢 还是看看怎么计算的
public void onConfigurationChanged(Configuration newParentConfig) {
mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
resolveOverrideConfiguration(newParentConfig);
mFullConfiguration.setTo(newParentConfig);
mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
onMergedOverrideConfigurationChanged();
if (!mResolvedTmpConfig.equals(mResolvedOverrideConfiguration)) {
// This depends on the assumption that change-listeners don’t do
// their own override resolution. This way, dependent hierarchies
// can stay properly synced-up with a primary hierarchy’s constraints.
// Since the hierarchies will be merged, this whole thing will go away
// before the assumption will be broken.
// Inform listeners of the change.
for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
mChangeListeners.get(i).onRequestedOverrideConfigurationChanged(
mResolvedOverrideConfiguration);
}
}
for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
mChangeListeners.get(i).onMergedOverrideConfigurationChanged(
mMergedOverrideConfiguration);
}
for (int i = getChildCount() - 1; i >= 0; --i) {
dispatchConfigurationToChild(getChildAt(i), mFullConfiguration);
}
}
mFullConfiguration.setTo(newParentConfig);
mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);
newParentConfig 为 传进来的一个congfig 首先将mFullConfiguration 设置为传进来的mFullConfiguration
然后再用mResolvedOverrideConfiguration 去更新mFullConfiguration
这是什么意思 就是首先设置成传进来的config 然后再结合mResolvedOverrideConfiguration 就是自身调整的config 组成自己的mFullConfiguration
那newParentConfig 其实就是自己父亲的mFullConfiguration 如果没有父亲就是null
为什么这么说 我们看一般怎么调用的onConfigurationChanged
onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);
到此就清楚了 mFullConfiguration 即为父亲的config(mFullConfiguration) 加上自己的mResolvedOverrideConfiguration 组合成自身的mResolvedOverrideConfiguration
是不是这个onConfigurationChanged 叫onParentConfigurationChanged 更合适呢? 我反正很疑惑为什么叫onConfigurationChanged
然后默认我们最终用的也就是mFullConfiguration
/**
- Returns full configuration applied to this configuration container.
- This method should be used for getting settings applied in each particular level of the
- hierarchy.
*/
public Configuration getConfiguration() {
return mFullConfiguration;
}
但是像 WindowState 子容器 还会重写自己的getConfiguration 。
@Override
public Configuration getConfiguration() {
// If the process has not registered to any display area to listen to the configuration
// change, we can simply return the mFullConfiguration as default.
if (!registeredForDisplayAreaConfigChanges()) {
return super.getConfiguration();
}
// We use the process config this window is associated with as the based global config since
// the process can override its config, but isn't part of the window hierarchy.
mTempConfiguration.setTo(getProcessGlobalConfiguration());
mTempConfiguration.updateFrom(getMergedOverrideConfiguration());
return mTempConfiguration;
}
之所以widowstate会重写 我觉得应该是因为 悬浮窗类似这样的窗口
至于getProcessGlobalConfiguration 这个config就不在这里说了
对于窗口就是getMergedOverrideConfiguration 去更新当前ProcessGlobalConfiguration
那mMergedOverrideConfiguration 又是啥呢?
void onMergedOverrideConfigurationChanged() {
final ConfigurationContainer parent = getParent();
if (parent != null) {
mMergedOverrideConfiguration.setTo(parent.getMergedOverrideConfiguration());
mMergedOverrideConfiguration.updateFrom(mResolvedOverrideConfiguration);
} else {
mMergedOverrideConfiguration.setTo(mResolvedOverrideConfiguration);
}
for (int i = getChildCount() - 1; i >= 0; --i) {
final ConfigurationContainer child = getChildAt(i);
child.onMergedOverrideConfigurationChanged();
}
}
很明显其就是自父节点到自身的所有请求的ResolvedOverrideConfiguration的和(当然这里说的和不是很准确 应该说是取并集且子类的覆盖父类的一个并)
没有父亲节点就是mResolvedOverrideConfiguration
到此就说完了
到这里是不是还有个以为mMergedOverrideConfiguration 和mFullConfiguration 有区别么?
大家觉得有区别么?
咋一看不都是当没有父亲的都是都是null 或者说empty么?
那差异哪来的呢 其实来源于DisplayContent
DisplayContent 的mFullConfiguration 和 mResolvedOverrideConfiguration 初始化就不一样 DisplayContent会主动更新mFullConfiguration
但这个更新不会去更新mResolvedOverrideConfiguration
(至于getProcessGlobalConfiguration 大致是使用的top 以及app请求的config 没细看 )
总的来说就是mRequestedOverrideConfiguration 记录当前容器主动请求的所有变更 mResolvedOverrideConfiguration 是各个子容器对mRequestedOverrideConfiguration的策略调整
mMergedOverrideConfiguration 是所有主动求情的变化即可(自父而下的累加 子请求等级高于父亲请求等级)
mFullConfiguration 就为当前容器的config