2019独角兽企业重金招聘Python工程师标准>>>

引言

今天我们主要讲的是SystemUI状态栏里面另一个常见的icons——notification icons,该icons主要用于显示app或者framework发送的各种notification icon,表示当前有新的通知来了,需要下拉通知栏进行查看,以达到提示用户的目的。

正文

本文主要从两个方面讲述下notification icon功能,主要分为初始化流程和通知icon显示流程
话不多说,我们开始吧。

初始化流程

首先我们看下状态栏的布局文件 status_bar.xml

<!-- The alpha of this area is controlled from both PhoneStatusBarTransitions andPhoneStatusBar (DISABLE_NOTIFICATION_ICONS). --><com.android.systemui.statusbar.AlphaOptimizedFrameLayoutandroid:id="@+id/notification_icon_area"android:layout_width="0dip"android:layout_height="match_parent"android:layout_weight="1"android:orientation="horizontal" /><com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"android:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal">

我们今天讲的notification icons就是这个 android:id="@+id/notification_icon_area" 了。
同样它最外层是一个AlphaOptimizedFrameLayout控件,前文已经说过类似的了,
SystemUI之状态栏status icon加载流程
该控件实现了hasOverlappingRendering()方法,该方法用来标记当前view是否存在过度绘制。

接下来我们看下SystemUI是怎么加载这个AlphaOptimizedFrameLayout

CollapsedStatusBarFragment.java

public void initNotificationIconArea(NotificationIconAreaControllernotificationIconAreaController) {ViewGroup notificationIconArea = mStatusBar.findViewById(R.id.notification_icon_area);mNotificationIconAreaInner =notificationIconAreaController.getNotificationInnerAreaView();if (mNotificationIconAreaInner.getParent() != null) {((ViewGroup) mNotificationIconAreaInner.getParent()).removeView(mNotificationIconAreaInner);}notificationIconArea.addView(mNotificationIconAreaInner);// Default to showing until we know otherwise.showNotificationIconArea(false);}

NotificationIconAreaController.java

/*** Initializes the views that will represent the notification area.*/protected void initializeNotificationAreaViews(Context context) {reloadDimens(context);LayoutInflater layoutInflater = LayoutInflater.from(context);mNotificationIconArea = inflateIconArea(layoutInflater);mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(R.id.notificationIcons);mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();}protected View inflateIconArea(LayoutInflater inflater) {return inflater.inflate(R.layout.notification_icon_area, null);}

如上,我们就找到了初始化的地方,主要是通过inflate这个R.layout.notification_icon_area文件,通过addView的方式添加到了AlphaOptimizedFrameLayout,下面就是看下R.layout.notification_icon_area这个文件了

<com.android.keyguard.AlphaOptimizedLinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/notification_icon_area_inner"android:layout_width="match_parent"android:layout_height="match_parent" ><com.android.systemui.statusbar.phone.NotificationIconContainerandroid:id="@+id/notificationIcons"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentStart="true"android:gravity="center_vertical"android:orientation="horizontal"/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
/*** A container for notification icons. It handles overflowing icons properly and positions them* correctly on the screen.*/
public class NotificationIconContainer extends AlphaOptimizedFrameLayout {}

从备注就能够看出来,这个就是所有notification icons的父控件,所有icons最后都是添加到这里面来的,
好了,到这里我们的第一部分初始化流程就讲完了。

通知icon显示流程

首先我们需要看下notification生成的地方

StatusBar.java

public void onNotificationPosted(final StatusBarNotification sbn,final RankingMap rankingMap) {if (isUpdate) {updateNotification(sbn, rankingMap);} else {addNotification(sbn, rankingMap);}
}public void addNotification(StatusBarNotification notification, RankingMap ranking)throws InflationException {String key = notification.getKey();if (DEBUG) Log.d(TAG, "addNotification key=" + key);mNotificationData.updateRanking(ranking);Entry shadeEntry = createNotificationViews(notification);protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn)throws InflationException {if (DEBUG) {Log.d(TAG, "createNotificationViews(notification=" + sbn);}NotificationData.Entry entry = new NotificationData.Entry(sbn);Dependency.get(LeakDetector.class).trackInstance(entry);entry.createIcons(mContext, sbn);// Construct the expanded view.inflateViews(entry, mStackScroller);return entry;}
}

层层调用之后,最后会通过entry.createIcons(mContext, sbn)生成notification icon,然后存放在NotificationData里面,感兴趣的可以看下entry.createIcons(mContext, sbn), 该函数里面主要生成了一个StatusBarIconView对象,这个就是最终显示在状态栏的icon。

notification生成的过程大致就是通过inflateViews(entry, mStackScroller)--->AsyncInflationTask处理加载然后生成ExpandableNotificationRow等的信息,最后通过StatusBar.java

@Overridepublic void onAsyncInflationFinished(Entry entry) {mPendingNotifications.remove(entry.key);// If there was an async task started after the removal, we don't want to add it back to// the list, otherwise we might get leaks.boolean isNew = mNotificationData.get(entry.key) == null;if (isNew && !entry.row.isRemoved()) {addEntry(entry);} else if (!isNew && entry.row.hasLowPriorityStateUpdated()) {mVisualStabilityManager.onLowPriorityUpdated(entry);updateNotificationShade();//  此处完成添加}entry.row.setLowPriorityStateUpdated(false);}private void updateNotificationShade() {................................................for (int i=0; i<toShow.size(); i++) {View v = toShow.get(i);if (v.getParent() == null) {mVisualStabilityManager.notifyViewAddition(v);mStackScroller.addView(v);}}................................................// Let's also update the iconsmNotificationIconAreaController.updateNotificationIcons(mNotificationData);//添加notification icons
}

updateNotificationShade这个函数回调完成view的添加,这个函数先是把inflate出来的通知,添加到NotificationScrollLayout里面,然后再添加notification icon,接下来我们就看下updateNotificationIcons里面的逻辑了。

NotificationIconAreaController.java

private NotificationIconContainer mNotificationIcons;
/*** Updates the notifications with the given list of notifications to display.*/public void updateNotificationIcons(NotificationData notificationData) {updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons,false /* showAmbient */);//  添加status bar notification iconupdateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons,NotificationShelf.SHOW_AMBIENT_ICONS);//  添加 notification self iconapplyNotificationIconsTint();}

主要的添加动作就在updateIconsForLayout这个函数中了

private void updateIconsForLayout(NotificationData notificationData,Function<NotificationData.Entry, StatusBarIconView> function,NotificationIconContainer hostLayout, boolean showAmbient) {ArrayList<StatusBarIconView> toShow = new ArrayList<>(mNotificationScrollLayout.getChildCount());// Filter out ambient notifications and notification children.for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {View view = mNotificationScrollLayout.getChildAt(i);if (view instanceof ExpandableNotificationRow) {NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();if (shouldShowNotificationIcon(ent, notificationData, showAmbient)) {toShow.add(function.apply(ent));}}}..................................................................................................................final FrameLayout.LayoutParams params = generateIconLayoutParams();for (int i = 0; i < toShow.size(); i++) {View v = toShow.get(i);// The view might still be transiently added if it was just removed and added againhostLayout.removeTransientView(v);if (v.getParent() == null) {hostLayout.addView(v, i, params);}}}

首先从mNotificationScrollLayout取出NotificationData,然后把NotificationData存放的StatusBarIconView取出添加到toShow里面,最后遍历添加到NotificationIconContainer中,这样就完成了往NotificationIconContainer添加icon的过程。

到这里,notification icon加载流程已经讲完,后面有时间还会讲下signal icon的加载流程,敬请关注。

转载于:https://my.oschina.net/u/920274/blog/3058509

SystemUI之状态栏notification icon加载流程相关推荐

  1. SystemUI 下拉通知栏快捷键加载流程

    1.下拉通知栏简介 2.源码位置 SystemUIService.javaframeworks/base/packages/SystemUI/src/com/android/systemui/Syst ...

  2. Android 4.0 ICS SystemUI浅析——StatusBar加载流程分析

    前面两篇文章< Android 4.0 ICS SystemUI浅析--SystemUI启动流程>.< Android 4.0 ICS SystemUI浅析--StatusBar结构 ...

  3. Android 8.1 中Systemui中的常见修改(六)NavigationBar加载流程

    本文主要分为两个部分 一.NavigationBar的加载流程 二.Android P上如何去除NavigationBar 一 NavigationBar的加载流程 NavigationBar就是我们 ...

  4. Launcher启动流程加载流程学习

     声明: 图片本来是有的 涉及到有些代码不能示人没有贴上,不过仅文字说也足够了,请广大老爷们自行下载源码参看流程分析阅读. 目录 一.认识Launcher: 1 1.功能 1 2.样式 2 3.And ...

  5. Android6.0 keyguard锁屏加载流程分析

    锁屏界面的加载通常在android中有两种方式触发:android系统开机和screenOff(灭屏)后,再screenOn; 先来看 android系统开机时候的锁屏加载流程: 首先在系统启动过程中 ...

  6. 总结Vue中index.html、main.js、App.vue、index.js之间关系以及Vue项目加载流程

    总结Vue中index.html.main.js.App.vue.index.js之间关系以及Vue项目加载流程 文章目录 总结Vue中index.html.main.js.App.vue.index ...

  7. Android----Allapps加载流程详解【AndroidICS4.0——Launcher系列五】

    工作需要总结,这样就能保证地基牢固,就能爬得更高: ----2013-01-07题记 转载请标明出处:http://blog.csdn.net/wdaming1986/article/details/ ...

  8. Android SIM卡识别加载流程

    文章目录 总述 代码路径 UICC框架 SIM卡识别加载流程 日志分析举例 总述 本文基于Android N(Android 7) 首先要知道SIM卡一般是挂载在CP侧(MODEM侧)的,由MODEM ...

  9. 【Android】恢复出厂后静态壁纸加载流程

    Android静态壁纸功能实现参与的类 /frameworks/base/core/java/android/app/WallpaperManager.java 给开发者提供方法调用.例:setBit ...

最新文章

  1. elastic-job的原理简介和使用
  2. 20170710L07-09-03老男孩Linux运维实战培训-Sersync实时同步软件实战应用指南07
  3. python文本提取_使用Python从HTML文件中提取文本
  4. ubuntu16.4下用jexus部署asp.net core rtm
  5. 信息学奥赛一本通(1012:计算多项式的值)
  6. java字符串反转及替换_Java圆括号翻转字符串
  7. Qt Creator 添加自定义注释
  8. 超级全面的MySQL优化面试解析
  9. No module named ‘lightgbm‘
  10. copy的过去式_copy的过去式和用法例句
  11. python爬虫什么意思-通俗的讲,网络爬虫到底是什么?
  12. 管理系统里用户角色与权限的设计
  13. word中间空白页删除技巧
  14. iOS-建设银行破解分享
  15. 神经网络基础05-注意力机制总结
  16. win7下用VS2008写视频聊天程序,求VFW教程?qzvgK
  17. 亚马逊买家秀视频怎么上传?上传买家秀视频的作用是什么
  18. nbd 相关概念及操作
  19. android 表情字符串,Android 显示输入法中的emoji表情以及String字符串转码
  20. SpringBoot整合RocketMQ

热门文章

  1. 763 划分字母区间
  2. Linux日常运维管理技巧(三)iptables规则备份和恢复、firewalld的9个zone、任务计划cron、chkconfig系统服务管理、添加服务命令、systemctl管理服务
  3. Nmap源码分析(整体架构)
  4. Python函数中参数* 和 ** 的区别
  5. 设计模式:抽象工厂模式(C++)【工厂方法升级】
  6. 小甲鱼Python第二十二讲课后习题
  7. iOS - UIControl
  8. 让TortoiseGit记住帐号密码方法
  9. 【微软亚洲研究院院长洪小文专访---谈大学生实习就业】
  10. 2019最后一个月Python继续霸榜,想上车?看这份书单