天天看点

Preference组件探究之Base,Support及AndroidX对比

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。

Preference组件探究之Base,Support及AndroidX对比

Base包的Preference组件自打Android发布来,效力了9大版本(Android 1 ~ 9),并将在Android 10(Android Q)被正式废弃。 

虽然非推荐并非禁止使用,但是官方不再维护的组件,尽量迁移至替代组件还是比较明智的选择。毕竟废弃了的API指不定埋下什么坑。

前面几篇文章花不少时间阐述了Base包的Preference组件的使用方法,原理解读和自定义方法。既然已经废弃了,那么这些探讨是不是毫无用处了呢?我觉得也不尽然,不管Preference组件再怎么变,其原理,使用方式不会差太大。

温故可以知新。

Android官方给的替代组件是AndroidX包的Preference组件。

Preference组件探究之Base,Support及AndroidX对比

AndroidX本是Jetpack使用的开源框架,如今Google将Support包也整合了进来。

在讲述AndroidX之前我们先介绍一下Support包下的Preference。

Support-Preference

Preference组件探究之Base,Support及AndroidX对比

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。

Preference组件探究之Base,Support及AndroidX对比

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,估计应该也是差不多的。

Preference组件探究之Base,Support及AndroidX对比

抛开一些注释和微小的代码优化,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文件或許可行。。。

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

原创不易,如果本篇文章引起你的思考和兴趣,欢迎点赞和关注。如果想要了解更多更全信息,扫码关注博主公众号「TechMerger」。

Preference组件探究之Base,Support及AndroidX对比