Android O Settings原始碼流程分析(資料載入之一級選單)
Android O Settings
資料載入之一級選單
DashboardSummary是頂級選單的容器,那麼資料的獲取和它也就有關係。
DashboardCategory的獲取是在DashboardSummary中的updateCategoryAndSuggestion方法中,獲取之後在DashboardAdapter設定
根據"com.android.settings.category"的值查詢子項資料,這裡的值為"com.android.settings.category.ia.homepage"。
在DashboardSummary的onCreate函式中有獲取的有兩個很重要數:mDashboardFeatureProvider
mDashboardFeatureProvider提供的資料是一級選單如"電池","顯示","網路和網際網路"等,
實現類為DashboardFeatureProviderImpl.java,而DashboardFeatureProviderImpl中的具體的資料是通過函式getTilesForCategory()從CategoryManager獲取的.
CategoryManager是SettingsLib這個靜態包中公共類,可以看一下:
可以看到CategoryManager是一個單例型別,這裡就是真正的資料載入位置,
載入是通過函式reloadAllCategories()呼叫tryInitCategories()獲取的.
到這裡為止,整個資料獲取的流程已經清楚,但是資料載入是在哪裡完成的呢,還要回到SettingsDrawerActivity中:
因為DashboardSummary啟動的生命週期已經結束,主要是完成一些物件的初始化工作(無資料),需要繼續分析Setting的onResume週期,最終呼叫的是SettingsDrawerActivity的onResume
在SettingsDrawerActivity中註冊了安裝應用狀態變化的廣播接收器等,但是這裡還進行了一個非同步操作:
new CategoriesUpdateTask().execute();
在這個AsyncTask中,doInBackground()呼叫了CategoryManager的reloadAllCategories()函式,而onPostExecute則呼叫了介面CategoryListener的唯一方法onCategoriesChanged(),那麼作為介面容器的DashboardSummary肯定過載了這個介面,實現了onCategoriesChanged()方法:
DashboardSummary在方法onCategoriesChanged()中進行了介面的重新整理,
mCategoryManager.reloadAllCategories(SettingsDrawerActivity.this, getSettingPkg());
reloadAllCategories函式中呼叫了tryInitCategories(),此函式中是獲取資料以及對資料的處理,來看下函式tryInitCategories:
在這裡呼叫了getCategories()方法;
具體獲取辦法追蹤到frameworks\base\packages\SettingsLib\src\com\android\settingslib\drawer\TileUtils.java中。
TileUtils.java:
(1)呼叫getTilesForAction()
(2)新建categoryMap集合
(3)遍歷tiles,判斷集合中是否有元素含有tile.category,如果沒有就執行createCategory
(4)將擁有相同屬性category的tile加入到物件DashboardCategory category物件的list<tile>集合中(兩個相同名字,一個是Tile裡面變數,一個是DashboardCategory物件)
(5)將categoryMap的值賦值給List <DashboardCategory>cagtories以便執行排序演算法
(6)遍歷cagtories利用Collections函式和比較器TILE_COMPARATOR將category.tiles按照priority從大到小排序
(7)利用Collections函式和比較器CATEGORY_COMPARATOR將categories按照priority從大到小排序
最後將載入的資料繫結到介面卡中。
首先是getTilesForAction()方法,組裝Intent物件。
然後呼叫getTilesForIntent()方法
(1)利用PM查詢所有含有getTilesForAction()生成的intent物件的ResolveInfo集合(<activity>標籤)
(2)獲取集合中每一個AcitvityManifest配置的meta標籤name包含com.android.settings.category的value值
(3)把activity name 和package 生成Intent物件
(4)將2步驟的值賦值給tile .category
(5)獲取action為com.android.settings.action.SETTINGS的intent-filter的priority屬性
(6)將解析meta-data標籤的bundle資料賦值給tile.metaData
注意:會過濾掉非系統級應用的資料!
在此方法中會呼叫updateTileData()方法
(1) 解析meta-data標籤 獲取name為 META_DATA_PREFERENCE_ICON的value值賦值給icon
(2)解析meta-data標籤 獲取name為 META_DATA_PREFERENCE_TITLE的resource值賦值給title
(3)解析meta-data標籤 獲取name為 META_DATA_PREFERENCE_SUMMARY的value值賦值給summary
(4)如果title為空就獲取acitvity標籤label屬性賦值給title
(5)如果icon等於0就獲取acitvity標籤icon屬性賦值給icon
createCategory()方法建立Category。
(1)建立DashboardCategory物件
(2)利用PM查詢所有含有Tile物件categoriyKey生成的intent物件的ResolveInfo集合
(3)把acitivity label值賦值給category title屬性
(4)把解析intent-filter標籤的priority值賦值給category屬性
對於第一級選單的載入。在AndroidManifest.xml中的配置如下列圖:(示例)
配置完之後會在onCategoriesChanged()中進行介面的載入。
由此可以知道 第一級選單完全是動態載入!