专栏首页猿湿XoongAndroid 8.0 SystemUI(三):一说顶部 StatusBar

Android 8.0 SystemUI(三):一说顶部 StatusBar

前言

大家好,我是 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 的初始化、分块、StatusIcon 块的添加和更新。
  • 二说内容计划是信号群icon与电池、时钟相关内容
  • 三说将抖抖 notification icon 相关内容。

目录

老规矩,先上目录。

StatusBar组成

按照T哥的分法,顶部StatusBar由4个部分组成,看下图。

图 1.1

图 1.2

图 1.1 是我在 8.0 模拟器上截的图,图 1.2 是布局 status_bar.xml 的组成。将图1.1标识与图1.2 id 一一对应。

  1. 对应的是notification_icon_area,平日里显示的都是notifications,如三方和系统的一些通知。
  2. 对应的是statusIcons,平日里显示的一些系统状态,如蓝牙、闹铃等。
  3. 是信号集群,显示的是信号相关的view,如wifi,cell信号格等,对应的是signal_cluster_view.xml。
  4. 则是剩余的两个独立的图标, 分别为电池电量显示、时间显示。

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 ---

本文分享自微信公众号 - 菜天(newbietian)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android Hybrid 混合开发初体验

    最近熟悉项目,就发现项目中用是原生框架 + Web 前端展示这种混合开发的形式。俗称 Hybrid(译:混合动力),典型的互联网 App 开发方式。

    菜天哥哥
  • 5 个 Android 工具 Apk,有效提升开发效率

    菜天哥哥
  • 效率 | 一条命令完成反编译apk操作

    最近又需要反编译 apk 和 manifest 文件,然后就扒拉扒拉,把以前私藏的库拿出来用。

    菜天哥哥
  • Linux基本操作:6w字搞定Linux手把手教程「心得体会」

    Linux命令这么多,该怎么从入门到精通?其实,这个事情非常的simple,这篇文章将会带你飞,文章非常的长,非常考验耐心。

    睡魔的谎言
  • 讲讲异方差的检验

    我们前面讲了异方差,也讲了怎么用图示法来判断是否有异方差,这一篇来讲讲怎么用统计的方法来判断有没有异方差。

    张俊红
  • 人生苦短,我用k8s--------------单节点二进制部署

    etcd是CoreOS团队于2013年6月发起的开源项目,基于go语言开发,目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raf...

    不吃小白菜
  • PHP实现简单汉字验证码

    经过粗略的搞吧搞吧,中文验证码也就显示出来了,当然一般网站使用的时候会有一个汉字库种子,从里面随机取出特定个数的汉字显示,最后就是记录到session进行验证了...

    梦_之_旅
  • 【Android 音视频开发打怪升级:OpenGL渲染视频画面篇】二、使用OpenGL渲染视频画面

    在第一篇文章【音视频基础知识】文章中,就介绍过,视频其实就是一张张图片组成的,在上文【初步了解OpenGL ES】中,介绍了如何通过OpenGL渲染一张图片,可...

    开发的猫
  • Rust入坑指南:核心概念

    今天要介绍的是Rust的一个核心概念:Ownership。全文将分为什么是Ownership以及Ownership的传递类型两部分。

    Jackeyzhe
  • Mac 10.13.x 的“安全性与隐私”的信任任何来源没了解决方法

    简单、

扫码关注云+社区

领取腾讯云代金券