前言
大家好,我是 ptt 。咱们继续 Android 8.0 SystemUI 的分析。
···
···
好吧,我承认很久没更新 SystemUI 的文章了,再次给大家道个歉。具体什么原因,可以看 上一篇文章 的最后。
不出意外,以后每周三会推一篇 SystemUI 的文章。有空余时间的话,其他时间也会发。
本文为 顶部StatusBar 的「第一说」,是的,有第一说就有第二说、第三说。目前是计划分三篇文章将 「顶部 StatusBar」相关逻辑大体讲完。
你没看错,是顶部 StatusBar。本来,按照T哥我的分法,SystemUI 的 StatusBar 是分为如下三步走的。起标题的话,也是起为StatusBar、Notification栏、QuickSettings。
而对于顶部 StatusBar,是打算一篇结束,分为四段:notification、statusIcon、signal集群、电池和时钟 各自的添加和更新。
但是,我发现 8.0 中顶部状态栏 notification icon 部分逻辑有了很大的改动。对比 7.0,多出了个NotificationInflater。并且,icon 和 expand 的逻辑流程是几乎相同的。
这就增加了分析 notification icon 相关流程的复杂度,虽然大概分析差不多了,但写出来很费时。
而对于signal信号群的添加与更新流程分析,也完全可以单拎出来搞一搞,或者和电池、时钟一起。
所以
目录
老规矩,先上目录。
StatusBar组成
按照T哥的分法,顶部StatusBar由4个部分组成,看下图。
图 1.1
图 1.2
图 1.1 是我在 8.0 模拟器上截的图,图 1.2 是布局 status_bar.xml 的组成。将图1.1标识与图1.2 id 一一对应。
StatusBar布局
那status_bar.xml这个布局又是如何被使用并加载的呢?
首先,让我们回顾一下 SystemUI 的启动流程:最终通过调用各自service组件的start方法,有序完成所有组件的初始化。SystemBars的start方法,通过读取strings中配置的类名,初始化对应的StatusBar组件。
在手机中,我们的StatusBar组件就是StatusBar.java。
要说status_bar.xml,不得不提的则是super_status_bar.xml。这个layout,一看名字就很super。它是整个status bar的 root 布局。它的加载流程如下:
StatusBar.java
-> start
-> createAndAddWindows
-> addStatusBarWindow
-> makeStatusBarView
-> inflateStatusBarWindow
变量mStatusBarWindow与其对应。它是一个StatusBarWindowView类,继承FrameLayout,负责整体框架上的排版和绘制,部分事件的监听及分发。
super_status_bar.xml 的布局主要包含以下部分。
其中的 id 为 status_bar_container 的布局,就是我们要找的对象。
当你再三的看这个id名的时候,相信你一定不陌生,xxx_container,没错,它也是个 FrameLayout。
平日里,我们使用 Fragment 都这么用。
果然,在 StatusBar 的 makeStatusBarView 方法中,status_bar_container 被替换为了一个Fragment。
这个CollapsedStatusBarFragment,只是一个container,包裹着几个部分。
在其onViewCreated中,加载了statusIcons布局。
我们要分析的 StatusIcon,在 Fragment 的 onViewCreated 中,开启了它罪恶的一生?不,它早已开启了罪恶的一生。
StatusIcon的初始化与更新
前面说了,StatusIcon块,主要负责的是系统状态的显示,比如蓝牙、闹铃、定位、省流量开关等。
这些Icon,都是系统预定好了是哪些。并在一个配置文件定义了slot,或者说是标签。如果你想加一个新类型图标,首先要修改的是这个文件中的config_statusBarIcons数组。
/frameworks/base/core/res/res/values/config.xml
那我们的 StatusBar 到底是如何初始化并更新这些Icon的?
根据 config_statusBarIcons这个id,仅仅发现了它在StatusBarIconControllerImpl 这个类中有被使用。而且是被传入父类构造方法中。
为了方便看清各类的关系,T哥一框一线画的类图送给你们。
其中:
1、Dependency 是SystemUI为了优化耦合依赖关系搞的类,在其start方法中,实例化了大量的Controller类,StatusBarIconContrllerImpl 在其中进行实例化。
2、StatusBar类 是 StatusBar 模块的核心类。
3、PhoneStatusBarPolicy 是负责StatusIcon的添加和更新,是StatusIcon初始化和更新的核心类。
4、StatusBarIconContrllerImpl 是 StatusBarIconController 实现类,提供对IconGroup(即IconManager)的管理。
5、StatusBarIconList 是 StatusBarIconControllerImpl 的父类,保存所有 Status Icon 的 Slot 和对应的Icon。
6、IconManager 负责和View打交道。仔细的同学,应该记得StatusIcon罪恶一生开始地方那两行代码,有DarkIconManager,并将view传入了DarkIconManager。
在SystemUIApplication启动各路服务时,第一被启动的服务组件是Denpendency,为什么?因为在服务数组中它排第一。
在Dependency的start方法中,实例化了impl类,故而根据配置初始化了icon的slot。
在StatusBar的start方法中, 待初始化完毕,实例化PhoneStatusBarPolicy。
PhoneStatusBarPolicy的构造方法,完成所有了StatusIcon的初始化和状态监听。
并在有相关图标状态发生改变后,调用impl的setIcon方法,判断后,进行更新操作。
在IconManager中,尤其是DarkIconManager,通过将生成的StatusBarIconView add to 或 remove from ViewGroup 或 设置 visible,完成 icon 的 显示与隐藏。
以下是 T哥一框一线画的时序图,送给你们。
最后
源码讲解本身就不容易,又是以微信公众号的方式进行, 故而T哥将代码部分能省则省,不能省的,都是用图来代替。
希望能提高你们的阅读质量。
但是,我是依据阅读分析源码写出的这篇文章,读者们理应边看源码边阅读,方能收获最大。
Android 6.0 - 7.0 - 8.0 每个版本的 StatusIcon 框架都有所改变,如果能看看之前版本,理解会更为深刻。
--- End ---