SystemUI之状态栏notification icon加载流程
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加载流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LInux CentOS6 无人值守安装
- 下一篇: 前端代码标准最佳实践:javascrip