1,概述

当configuration发生变化后,Activity方法onConfigurationChange会被调用,在此具体记录configuration更新在Framework中的调用过程,直至传入Activity;

2,源码

configuration包含一个应用对手机配置的感知,比如窗口大小、重力方向、手机模式等,可以查看具体成员,

 

ok,包含配置文件的容器是ConfigurationContainer类,主要成员如下:

    /*** 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();/** True if mRequestedOverrideConfiguration is not empty */private boolean mHasOverrideConfiguration;/*** 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();

mRequestedOverrideConfiguration是原始request,container简单将新配置用它保存;mResolvedOverrideConfiguration是特殊处理后的configuration,子类可以通过重写resolveOverrideConfiguration方法修改其中的配置,达到特殊化,父类只是简单将原始request保存到它,并未改写;

mFullConfiguration是实际更新后configuration的最终状态;

mMergedOverrideConfiguration是具备继承效应的configuration,即container改变configuration后,子类将继承此改变,以此类推;

具体,咱们看ConfigurationContainer.onConfiguration方法,

public void onConfigurationChanged(Configuration newParentConfig) {//临时configuration变量,保存更新之前的mResolvedOverrideConfigurationmResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);//更新mResolvedOverrideConfiguration,可重写此方法增添特殊配置resolveOverrideConfiguration(newParentConfig);mFullConfiguration.setTo(newParentConfig);//根据差异更新最终状态:mFullConfigurationmFullConfiguration.updateFrom(mResolvedOverrideConfiguration);//合并此次修改,保存至mMergedOverrideConfigurationonMergedOverrideConfigurationChanged();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) {//传达configuration最终状态到子类final ConfigurationContainer child = getChildAt(i);child.onConfigurationChanged(mFullConfiguration);}}

查看onRequestedOverrideConfigurationChanged方法,当有配置request到达,调用onConfigurationChanged完成上一步;

public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {// Pre-compute this here, so we don't need to go through the entire Configuration when// writing to proto (which has significant cost if we write a lot of empty configurations).mHasOverrideConfiguration = !Configuration.EMPTY.equals(overrideConfiguration);mRequestedOverrideConfiguration.setTo(overrideConfiguration);// Update full configuration of this container and all its children.final ConfigurationContainer parent = getParent();onConfigurationChanged(parent != null ? parent.getConfiguration() : Configuration.EMPTY);}

进入下一步,Activity如何感知到配置的改变?这是一个binder过程,先从Activity生命周期说起;

配置改变后通过binder调用IApplicationThread.scheduleTransaction方法,

public void schedule() throws RemoteException {mClient.scheduleTransaction(this);}

然后配置改变消息会进入应用进程,经过ActivityThread.H发送消息,执行Transaction,进入TransactionExecutor.executeCallbacks方法,

这个ClientTransactionItem.execute方法如下,

 @Overridepublic void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {// TODO(lifecycler): detect if PIP or multi-window mode changed and report it here.Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");client.handleActivityConfigurationChanged(token, mConfiguration, INVALID_DISPLAY);Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);}

最终调用到performActivityConfigurationChanged方法,执行如下分支,回调Activity.onConfiguration方法,完成应用进程回调;

if (shouldReportChange) {activity.mCalled = false;activity.onConfigurationChanged(configToReport);if (!activity.mCalled) {throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +" did not call through to super.onConfigurationChanged()");}}

那么系统进程如何传送配置信息到应用进程?这个还得从配置改变说起;

ConfigurationContainer是一个抽象类,直接子类是WindowContainer

WindowContainer是应用Window容器,所有顶层WindowContainer的容器是RootWindowContainer类,当configuration更新后,wms会调用setDisplayOverrideConfigurationIfNeed方法,然后通过ConfigurationContainer前文介绍的方法依次通知children配置update信息;

void setNewDisplayOverrideConfiguration(Configuration overrideConfig,@NonNull DisplayContent dc) {if (dc.mWaitingForConfig) {dc.mWaitingForConfig = false;mLastFinishedFreezeSource = "new-config";}mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, dc);}

于是乎,通过children调用至ActivityStack.onConfiguration,它继承WindowContainer,

该方法末尾,调用resize方法,再调用ensureVisibleActivitiesConfiguration方法;

void ensureVisibleActivitiesConfiguration(ActivityRecord start, boolean preserveWindow) {mEnsureVisibleActivitiesConfigHelper.process(start, preserveWindow);}

process方法内,会更新配置,然后更新焦距中的Activity

 final PooledFunction f = PooledLambda.obtainFunction(EnsureVisibleActivitiesConfigHelper::processActivity, this,PooledLambda.__(ActivityRecord.class));forAllActivities(f, start, true /*includeBoundary*/, true /*traverseTopToBottom*/);f.recycle();if (mUpdateConfig) {// Ensure the resumed state of the focus activity if we updated the configuration of// any activity.mRootWindowContainer.resumeFocusedStacksTopActivities();}

进一步查看processActivity方法,

boolean processActivity(ActivityRecord r) {mUpdateConfig |= r.ensureActivityConfiguration(0 /*globalChanges*/, mPreserveWindow);mBehindFullscreen |= r.occludesParent();return mBehindFullscreen;}
跟进ensureActivityConfiguration,在ActivityRecord.ensureActivityConfiguration方法中,有如下代码,
if (changes == 0 && !forceNewConfig) {if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,"Configuration no differences in " + this);// There are no significant differences, so we won't relaunch but should still deliver// the new configuration to the client process.if (displayChanged) {scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);} else {scheduleConfigurationChanged(newMergedOverrideConfig);}return true;}

displayChanged未改变的前提下,走scheduleConfigurationChange,通知应用进程,

private void scheduleConfigurationChanged(Configuration config) {if (!attachedToProcess()) {if (DEBUG_CONFIGURATION) Slog.w(TAG,"Can't report activity configuration update - client not running"+ ", activityRecord=" + this);return;}try {if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "+ config);mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,ActivityConfigurationChangeItem.obtain(config));} catch (RemoteException e) {// If process died, whatever.}}

至此,应用进程可以根据新配置更新布局等信息。

【android】configuration相关推荐

  1. 【Android】Android Studio 1.5+ 中混合调试Native和Java代码

    [Android]Android Studio 1.5+ 中调试Native和Java代码 Android Studio 1.5+表示Android Studio 1.5版本以及以上. 网上大部分中文 ...

  2. 【Android】OkHttp源码解读逐字稿(2)-OkHttpClient

    目录 0.前言 1.各个属性浅析 01.dispatcher 02.connectionPool 03.interceptors&networkInterceptors 04.eventLis ...

  3. 【Android】Parse开发笔记(1)—— 准备

    一.简介 Parse是由 YC 孵化出来的.专为移动应用提供后台服务的云计算平台,为开发者包办繁琐的后台服务,让开发者只需专注于具体的开发工作.它提供任意数据保存.照片或其它文件存储.发送推送通知.创 ...

  4. 【Android】显示Emoji表情字符

    一.下载AndroidEmoji.ttf字体 地址1:Github Android Platform 地址2:AndroidEmoji.ttf.zip 二.使用 2.1 将字体拷贝到assets/fo ...

  5. 【Android】Eclipse自动编译NDK/JNI的三种方法

    [Android]Eclipse自动编译NDK/JNI的三种方法 SkySeraph Sep. 18th  2014 Email:skyseraph00@163.com 更多精彩请直接访问SkySer ...

  6. android编程中添加gif,Android应用开发之【Android】使用android-gif-drawable包加载GIF动图...

    本文将带你了解Android应用开发之[Android]使用android-gif-drawable包加载GIF动图,希望本文对大家学Android有所帮助. [导包] 首先需要导入android-g ...

  7. 【Android】保存Fragment切换状态

    [Android]保存Fragment切换状态 前言 一般频繁切换Fragment会导致频繁的释放和创建,如果Fragment比较臃肿体验就非常不好了,这里分享一个方法. 声明 欢迎转载,但请保留文章 ...

  8. 【Android】3.0 第3章 百度地图及其应用--预备知识

    分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 一.概述 这一章先来点有意思的百度地图应用示例,然后再分章详细介绍用C#开发Android App的各种基本技 ...

  9. 【Android】Vitamio 4.0 公测版发布(2013-05-28)

    更新 Vitamio 4.0 正式版已经发布! 这里:[Android]Vitamio 4.0 正式版发布/ Vitamio IOS 测试版发布(2013-07-16) 正文 一.下载地址 Vitam ...

最新文章

  1. 使用 coding.net 发布你的个人博客
  2. 第5章-无人机UAV模型分析
  3. HTML带有圆点的列表,HTML 列表
  4. C/C++ 字符串(string)转换
  5. Delphi及C++Builder经典图书一览表(持续更新中2018.01.02)
  6. 高通在物联网领域已经深耕多年
  7. spl_autoload_register函数
  8. Homebrew命令具体解释
  9. 华为怒发公开信;锤子手机难产罗永浩陷尴尬处境;苹果错失 5G | 极客头条
  10. ADO.NET实例教学一
  11. win10下载日文输入法时,无法使用日文键盘的问题解决
  12. Excel中实用的3个数据透视表操作技巧,简单高效!
  13. Hadoop生态圈(十八)- HDFS Transparent Encryption透明加密
  14. 2022-2028年全球与中国工业用智能眼镜行业产销需求与投资预测分析
  15. 夜深人静写算法(三十四)- 逆元
  16. Android科大讯飞语音按队列播报
  17. 逆谐波滤波matlab,基于MATLAB仿真的SPWM逆变电路谐波分析及滤波器设计
  18. 自动阅读是骗人的吗?新手一定要看,避免入坑
  19. 摄像头8mm可以看多远_监控摄像头有多少种,如何来选型
  20. C语言编程:密码解密

热门文章

  1. 【入侵检测】window下安装snort
  2. Python均匀分布和三角形分布
  3. yum 安装 npm
  4. 关于虚拟屏使用的权限问题
  5. 爬虫平台的架构实现和框架的选型(二)
  6. java画空心金字塔
  7. 考公知识积累——人文常识
  8. 决策树-CART(上)
  9. android videoview 隐藏 播放按钮
  10. 财神:为何你怎么辛苦赚钱,却赚不到多少?