关键字:Configuration,屏幕旋转,语言切换,字体切换, 源码
前段时间做了关于系统字体切换的功能,其中涉及到较多ConfigurationChanged的流程。屏幕旋转、mcc、系统语言切换等均是通过该流程来实现的。
网上少有这方面的描述,故将该部分总结提炼出来做个小结。
以下以屏幕旋转为例。关于屏幕旋转对于Activity的生命周期的影响也在以下可以体现。
ConfigurationChange Flow
讲太多也不如一个图来得实在,下图也是整个ConfigurationChange通用流程的概括,该流程是基于Android 5.1 和6.0画出,kk版本应该也是差不多的。图片请放大来看。
流程跟踪
下面是对屏幕旋转的事件跟踪,尽量干货.
注:有序列表标号代表对应上图中的时序节点
1.屏幕旋转事件上传
G-Sensor将旋转事件由底层上传到FW处理,改变Configuration中orientation的值并将事件继续上传:
Configuration中对屏幕方向的定义:
/**
* Overall orientation of the screen. May be one of
* {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
*/
public int orientation;
调用ActivityManagerNative.getDefault().updatePersistentConfiguration(newConfig);将事件上传
2.ActivityManagerNative中使用远程代理通过Binder调用AMS的同名方法updatePersistentConfiguration
(远程代理这块不作深入了解)
public void updatePersistentConfiguration(Configuration values) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
values.writeToParcel(data, 0);
mRemote.transact(UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
然后在AMS中,遍历每一个最近运行的程序,同步顺序执行以下方法
/**
* Do either or both things: (1) change the current configuration, and (2)
* make sure the given activity is running with the (now) current
* configuration. Returns true if the activity has been left running, or
* false if <var>starting</var> is being destroyed to match the new
* configuration.
* @param persistent TODO
*/
boolean updateConfigurationLocked(Configuration values, ActivityRecord starting, boolean persistent, boolean initLocale) {
...
mSystemThread.applyConfigurationToR