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.javapublic 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 VS Support VS AndroidX
  Base Support AndroidX
引入 Andoid 1.0 Andoid 7.0 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的到来!

--------------------------------------------------------------------------------------------------------------------------------------------------------------

20200304更新

android Q的時候frameworks/support的源碼已經從AOSP倉庫的主分支(master)裏移動到了androidx分支(androidx-master-dev),參考如下提交。

 https://android-review.googlesource.com/c/platform/prebuilts/sdk/+/896475
 Import Support Library, AndroidX from build 5280039

prebuilts/sdk/current/androidx-README.md文件裏可以看到説明。
如果需要查看的源碼的話,在prebuilts/sdk/current/androidx下搜索-sources.jar命名的jar包。
 比如recyclerview的代碼為recyclerview-1.1.0-alpha07-sources.jar。參與編譯的為recyclerview-1.1.0-alpha07.aar。
如果需要修改代碼的話,需要切到androidx-master-dev倉庫去貢獻代碼。

這種變化使得想要在源碼裏修改support邏輯變得困難。
 取得源碼自行編譯后得到class文件替換prebuilts下面的aar文件或許可行。。。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

更多相关文章

  1. Android(安卓)XML属性介绍
  2. Android(安卓)实用工具Hierarchy Viewer实战
  3. android 高级组件之Spinner
  4. Android基础和运行机制
  5. Android--About Android(欢迎修改、补充)
  6. Android(安卓)--Intent意图的讲解
  7. Android基本控件模板
  8. Android(安卓)如何让EditText不自动获取焦点
  9. Android中禁止多点触控的设置

随机推荐

  1. 升级 Android(安卓)Studio 3.2.1 后出现
  2. Android(安卓)调用系统相机 失败
  3. android]Android(安卓)线程优先级修改
  4. Android(安卓)UI元素使用初步
  5. Android(安卓)随时随地键值对存储对象解
  6. android使用SmartRefreshLayout库实现下
  7. 两个星期的Android开发
  8. 学习Android从0开始之基础篇(3)-视图组件之
  9. 全球支持最多运行平台的NoSQL数据库 iBox
  10. Android(安卓)Bitmap 缩放 旋转 水印 裁