1. 程式人生 > >Android O Settings原始碼流程分析(資料載入之一級選單)

Android O Settings原始碼流程分析(資料載入之一級選單)

Android O Settings 

資料載入之一級選單

DashboardSummary是頂級選單的容器,那麼資料的獲取和它也就有關係。

DashboardCategory的獲取是在DashboardSummary中的updateCategoryAndSuggestion方法中,獲取之後在DashboardAdapter設定

根據"com.android.settings.category"的值查詢子項資料,這裡的值為"com.android.settings.category.ia.homepage"。

在DashboardSummary的onCreate函式中有獲取的有兩個很重要數:mDashboardFeatureProvider

,mSuggestionFeatureProvider.這兩個是主要的資料提供者,mSuggestionFeatureProvider和mDashboardFeatureProvider的資料獲取是有所不同的,重點說明下mDashboardFeatureProvider.

mDashboardFeatureProvider提供的資料是一級選單如"電池","顯示","網路和網際網路"等,

實現類為DashboardFeatureProviderImpl.java,而DashboardFeatureProviderImpl中的具體的資料是通過函式getTilesForCategory()從CategoryManager獲取的.

CategoryManager是SettingsLib這個靜態包中公共類,可以看一下:

可以看到CategoryManager是一個單例型別,這裡就是真正的資料載入位置,

載入是通過函式reloadAllCategories()呼叫tryInitCategories()獲取的.

到這裡為止,整個資料獲取的流程已經清楚,但是資料載入是在哪裡完成的呢,還要回到SettingsDrawerActivity中:

因為DashboardSummary啟動的生命週期已經結束,主要是完成一些物件的初始化工作(無資料),需要繼續分析Setting的onResume週期,最終呼叫的是SettingsDrawerActivity的onResume

()方法。

在SettingsDrawerActivity中註冊了安裝應用狀態變化的廣播接收器等,但是這裡還進行了一個非同步操作:

new CategoriesUpdateTask().execute();

在這個AsyncTask中,doInBackground()呼叫了CategoryManagerreloadAllCategories()函式,而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()中進行介面的載入。

由此可以知道 第一級選單完全是動態載入