Android提供的Preference組件使得APP設置頁面的開發變得簡單。
除了上述幾篇文章討論的Base包的Preference組件外,Android還提供了更爲高效的Support包的Preference組件。
甚至於即將發佈的Android Q預期將Support包的Preference組件全面替換爲AndroidX包的組件。
本篇文章我們將探討這三種Preference組件。
從Android官網的描述我們知道,Base包的Preference組件自Android 1.0(API 1)開始引入,並於Android Q(API 29)變爲非推薦API。
Base包的Preference組件自打Android發佈來,效力了9大版本(Android 1 ~ 9),並將在Android 10(Android Q)被正式廢棄。
雖然非推薦並非禁止使用,但是官方不再維護的組件,儘量遷移至替代組件還是比較明智的選擇。畢竟廢棄了的API指不定埋下什麼坑。
前面幾篇文章花不少時間闡述了Base包的Preference組件的使用方法,原理解讀和自定義方法。既然已經廢棄了,那麼這些探討是不是毫無用處了呢?我覺得也不盡然,不管Preference組件再怎麼變,其原理,使用方式不會差太大。
溫故可以知新。
Android官方給的替代組件是AndroidX包的Preference組件。
AndroidX本是Jetpack使用的開源框架,如今Google將Support包也整合了進來。
在講述AndroidX之前我們先介紹一下Support包下的Preference。
Support-Preference
Preference組件於版本24引入到了support V7中。
從官網的描述中我們知道support包採用RecyclerView控件展示PreferenceScreen上的組件。
使用性能更好的RecyclerView代替了ListView使得support包的Preference組件更爲高效。
V7
PreferenceFragmentCompat的源碼看得出來內部加載了RecyclerView控件。
// frameworks/support/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
public abstract class PreferenceFragmentCompat extends Fragment … {
public View onCreateView(…) {
…
final RecyclerView listView = onCreateRecyclerView(themedInflater, listContainer,
savedInstanceState); // 默認加載了RecyclerView控件
if (listView == null) {
throw new RuntimeException("Could not create RecyclerView");
}
mList = listView;
…
return view;
}
}
Support包的PreferenceFragmentCompat除了提供像Base包一樣的addPreferencesFromResource()外還提供瞭如下方法。
setPreferencesFromResource()
定義:用於複寫指定key的PreferenceScreen。
原理:比addPreferencesFromResource()多了一個查找目標key的PreferenceScreen的過程。
onCreatePreferences()
定義:提供給子類複寫用來指定Preference佈局的抽象方法。
使用:子類複寫後可以調用addPreferencesFromResource()或setPreferencesFromResource()去加載佈局,也可以直接創建Preference組件後手動添加到PreferenceScreen。
原理:onCreate()的最後將默認調用這個抽象方法去執行子類的配置。
除了上述的PreferenceFragmentCompat如下網址顯示V7下面還有一大堆和Base包差不多名稱的Preference相關類,使用方法也大同小異。
https://developer.android.google.cn/reference/android/support/v7/preference/package-summary
其中有一個類需要關注下:PreferenceViewHolder。
PreferenceViewHolder是support-v7包下加入的RecyclerView$ViewHolder子類。
內部持有title,summary等Preference內控件,用於Preference組件下緩存RecyclerView元素。
PreferenceScreen通過PreferenceGroupAdapter和RecyclerView綁定。
PreferenceGroupAdapter#onCreateViewHoler()回調時將加載Preference佈局,得到itemView後封裝爲PreferenceViewHolder對象進行緩存。
並調用Preference#onBindViewHolder()進行初始化。
所以如果想自定義Support包的Preference組件的話需要複寫onBindViewHolder()。
除了V7,V14,V17包都含有Preference組件。
V14
新引入瞭如下組件。
SwitchPreference和V7-SwitchPreferenceCompat一樣,改了名字
PreferenceFragment 和V7-PreferenceFragmentCompat一樣,改了名字
PreferenceDialogFragment 帶Dialog的PreferenceFragment抽象基類
EditTextPreferenceDialogFragment 佈局爲輸入框的PreferenceDialogFragment
ListPreferenceDialogFragment 佈局爲列表選擇的PreferenceDialogFragment
MultiSelectListPreference 佈局爲列表選擇的DialogPreference
MultiSelectListPreferenceDialogFragment 佈局爲多選列表的PreferenceDialogFragment
V17
BaseLeanbackPreferenceFragment 類似瑞士軍刀風格leanback風格的PreferenceFragment抽象基類,內部集成了VerticalGridView控件
LeanbackPreferenceFragment 外層包裹了標題的BaseLeanbackPreferenceFragment子類
LeanbackSettingsFragment 根佈局爲LeanbackSettingsRootView的Fragment組件,主要和LeanbackPreferenceFragment配合使用
LeanbackPreferenceDialogFragment 帶DialogPreference的Fragment組件
LeanbackListPreferenceDialogFragment 帶List
Preference的LeanbackPreferenceDialogFragment組件
Android基於大屏幕設備推出了leanback導航模式並引入到了V17中,上述的Preference相關組件都是基於leanback風格的相應擴展組件。
AndroidX
我們回到起初說到的替代組件:AndroidX包的Preference組件。
可以跟隨官方的如下說明將Support包遷移至AndroidX。
https://developer.android.google.cn/jetpack/androidx/migrate
如下網址展示了AndroidX所有的class列表。
https://developer.android.google.cn/reference/androidx/classes
Support-v7, v14下的Preference組件全部遷移到了androidx.preference包下。
Support-v17下的Preference組件全部遷移到了androidx.leanback.preference包下。
按照官方的說法。只是將Support包的代碼整合到了AndroidX中。實際是不是這樣呢?
AndroidX代碼是開源的。
AndroidX源碼網址:https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev
在Android系統的源碼目錄:frameworks/support/preference/src/main/java/androidx/preference/
Support VS AndroidX
將Support包和AndroidX包中最基礎的Preference類分別取出並diff。
經過diff我發現兩個java文件除了大量的格式,書寫風格的差異以外,代碼邏輯幾乎完全一致。
Preference以外的文件沒有diff,估計應該也是差不多的。
拋開一些註釋和微小的代碼優化,AndroidX果真只是針對Support包的簡單整合。
我們將Base包,Support包及AndroidX包下的Preference做下總結。
Base | Support | AndroidX | |
引入 | Andoid 1.0 | Andoid 2.3 | Andoid 10.0 |
棄用 | Andoid 10.0 | 爲了兼容暫未棄用 | - |
包名 | android.preference | android.support.v7.preference android.support.v14.preference android.support.v17.preference |
androidx.preference androidx.leanback.preference |
原理 | 採用ListView控件展示 | 採用RecyclerView控件展示 | 採用RecyclerView控件展示 |
源碼 | frameworks/base/core/ java/android/preference/ |
frameworks/support/v7/preference/ frameworks/support/v14/preference/ frameworks/support/v17/preference-leanback/ |
frameworks/support/preference/ frameworks/support/leanback-preference |
Base包的Preference使用的ListView在性能表現,內存佔用,擴展支持等方面已經落後於RecyclerView。在經歷了9大版本之後即將謝幕,交棒給AndroidX。
雖然將被棄用,但其實現思路,公開API和使用文檔深深地影響了Support包的Preference的設計。在Android平臺上的設置模塊它是當之無愧的元老。其關於Preference的設計理念也被Support和AndroidX很好地繼承和發揚。
讓我們一起感謝android.preference的付出,歡迎androidx.preference的到來!