1. 程式人生 > >Android N Settings模組與Android M Settings模組差異

Android N Settings模組與Android M Settings模組差異

Android N Settings 與之前的Android版本Settings模組在UI上右較大的改變,最直觀的差異在於Android N 設定介面增加了向右滑動的抽屜效果。

先回想下android M設定的主介面時怎麼顯示和互動的?

android M設定的主介面是定義在res/xml/dashboard_categories.xml這個檔案中,其SettingsActivity.java繼承與Activity,在其onCreate方法中,通過mIsShowingDashboard變數,控制載入不同的佈局R.layout.settings_main_dashboard或者 R.layout.settings_main_prefs

Settings的主介面或者二級三級選單),mIsShowingDashboard Boolear型別的變數是直接判斷當前要啟動的Activity的類是不是Settings.class,因為Settings這個類才是Settings的入口類。若是載入Settings的主介面,則是載入R.layout.settings_main_dashboard佈局,這個佈局裡面僅僅只是一個FrameLayoutViewContainer

SettingsActivity.javabuildDashboardCategories()->loadCategoriesFromResource(R.xml.dashboard_categories, categories, this) ->updateTilesList

()去解析這個佈局檔案,動態新增或刪除一級選單的item,然後將主介面載入到FrameLayoutViewContainer中,這樣一級選單就顯示出來了。

對於二級選單,在設定模組中有一個Settings.java的類,該類中定義了許多直接繼承與SettingsActivity的空實現Activity,如果細心點還會發現,這些空實現的ActivityAndroidMainifest.xml中都有<meta-data/>屬性,這是為什麼呢?原因很簡單,上面說過,既然這些Activity都是繼承與SettingsActivity,那麼要啟動這些Activity時必然會走SettingsActivity

onCreate()方法,剛在還提到SettingsActivityonCreate()方法是需要載入一級選單還是載入二級選單,取決於mIsShowingDashboard變數,而現在要確定載入的是二級選單的具體哪個選單?則需要用到AndroidMainifest.xml中宣告該Activity時定義的<meta-data/>屬性。

當然,並不是所有的設定項都是這樣,例如若要在Settings中新增一個選項,跳轉到其他應用中,那麼也可以直接在dashboard_categories.xml中新增相應的item,直接用intent跳轉過去也時可以的。

那麼,Android N中的設定主介面又時怎麼顯示和互動的呢?

Android N 在程式碼架構上和Android M最大的區別是Android N設定程式碼分為了兩部分,一部分是在packages/apps/Settings,另一部分是在frameworks/base/packages/SettingsLib

Android N Settings增加了向右滑動的抽屜效果,即無論在一級二級還是三級選單介面下,只要向右滑動就可以調出Settings的主介面(事實上是無論哪一級選單,只要改級選單繼承了SettingsActivity,那麼就可以向右滑動調出設定的主介面)。接下來分析Android N Settings的啟動流程。

先看設定的入口類,Settings.java,該類和之前一樣,沒什麼變化,一樣繼承與SettingsActivity.java,內部也定義了很多空實現的內部類,空Activity繼承與SettingsActivity。那麼應該和android M一樣,真正的入口還是在SettingsActivity中。直接看SettingsActivity類,發現SettingsActivity不再是繼承與Activity類,而是繼承與rameworks/base/packages/SettingsLib下面的SettingsDrawerActivity,看一下SettingsDrawerActivity是什麼鬼??

SettingsDrawerActivity從名字來看,好像和實現滑動效果有關,到該類一看究竟,發現它載入的佈局時settings_with_drawer.xml,這個佈局中用到android.support.v4.widget.DrawerLayoutDrawerLayout 佈局就具有左右滑動的抽屜效果。在看settings_with_drawer.xml佈局中有一個listView控制元件,猜想該控制元件就是用來顯示抽屜佈局中的設定的主介面(後面在分析)。

繼續看SettingsActivityonCreate方法,其載入佈局的地方和之前沒什麼區別,可是卻發現有區別的地方在從DashboardSummary.class中的獲取要載入item的資料部分,DashboardSummary.javarebuildUI()中,呼叫了SettingsDrawerActivitygetDashboardCategories()獲取資料。也就是說在設定中主介面上要顯示那些選項也是rameworks/base/packages/SettingsLib中的SettingsDrawerActivitygetDashboardCategories()獲取來的,而不是像Android M一樣將佈局定義在res/xml/dashboard_categories.xml,現在在Settings模組下面已經沒有了dashboard_categories.xml檔案,那麼資料到底是怎麼獲取出來的呢?

現在來分析SettingsDrawerActivity類,在SettingsDrawerActivityonCreate方法中,如上面提到,它載入的佈局是settings_with_drawer.xml,它是外層是DrawerLayout,所以能左右滑動(可自行百度DrawerLayout用法),該佈局中有listView,這個listView就是我們左右滑動看到的DrawerLayout的主介面,listViewAdapterSettingsDrawerAdapter的例項,SettingsDrawerAdapter繼承於BaseAdapter,SettingsDrawerActivity中通過getDashboardCategories()   >TileUtils.getCategories(this, sTileCache),獲取的資料,它將資料也是封裝成DashboardCategory型別。

再來看 TileUtils類的getCategories()是如何返回DashboardCategory物件的List?先看程式碼:

 

getCategories()方法差不多可分為三步:

1.先呼叫getTilesForAction() ->getTilesForInten()從AndroidMainifast.xml中宣告的activity資訊中解析,並將解析的資料以Tile型別資料結構封裝。

2,遍歷儲存所有Tile的集合,將通過tile.category屬性,將其分類,並構建成category,並將category儲存在對應的categoryMap中。

3.構建categories,並且排序,排序是按照DashboardCategorypriority排序的。

先看一下Title資料型別,它裡面封裝的每一個變數都是和AndroidMainifast.xml中宣告Activity<meta-data/>標籤一一對應的。

 

Title  : 對應每個item顯示的標題

icon   :對應每個Item顯示的圖示

summary  : 對應每個item顯示的詳細資訊,summary

intent  :item 對應的intent

cetagory :item 屬於哪一個catagory

priority  : item 的位置有關,排序會用到

extras  Optional additional data for use by subclasses of the activity,從啟動它的類攜帶過來的資訊

meta-data The metaData from the activity that defines this tile,定義的meta-data

通過這樣的方法獲取到了Settings主選單和左後滑動抽屜效果需要顯示的資料,然後將資料拋給SettingsDrawerAdapter,在它的getView方法中去建立對應的view,就將介面展示出來了。

總結一下:到了Android N設定中沒有主介面顯示的佈局檔案,而是直接解析AndroidManifast.xml檔案,從該檔案中獲得並處理要顯示的資訊。