(一百九十)Android Jetpack 学习(四)—— 偏好设置

前言:偏好设置如果是负责设置模块的同学就会非常熟悉,我虽然很熟悉,但是没有系统地看过官方文档,都是看参考设置以及学习设置源码的,也许会有所缺漏。

学习:https://developer.android.google.cn/guide/topics/ui/settings

 

设置   

注意:本指南介绍如何使用 AndroidX Preference Library。自 Android 10 开始,系统已弃用 android.preference 库平台。

设置使用户能够改变应用的功能和行为。设置可以影响后台行为,例如应用与云同步数据的频率;设置的影响还可能更为深远,例如改变用户界面的内容和呈现方式。

建议使用 AndroidX Preference Library 将用户可配置设置集成至您的应用中。此库管理界面,并与存储空间交互,因此您只需定义用户可以配置的单独设置。此库自带 Material 主题,可在不同的设备和操作系统版本之间提供一致的用户体验。

 

简单入门的参考https://developer.android.google.cn/guide/topics/ui/settings

本文主要学习下之前有缺漏的部分

 

Control Preference 可见性

您可以在用户跳转至设置屏幕时,控制哪些 Preferences 对用户可见。 例如,如果某个特定 Preference 仅在对应功能启用时才有意义,则您可能想在该功能停用时隐藏该 Preference

要仅在符合某项条件时显示 Preference,首先要在 XML 中将 Preference 可见性设置为 false,如以下示例所示:

<EditTextPreference
        app:key="signature"
        app:title="Your signature"
        app:isPreferenceVisible="false"/>

接下来,当符合相应条件时,在 onCreatePreferences() 中显示 Preference

KotlinJava

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    setPreferencesFromResource(R.xml.preferences, rootKey);
    if(*/\*some feature\*/*) {
        Preference editTextPreference = findPreference("signature");
        editTextPreference.setVisible(true);
    }
}

这边学习一下,之前项目的实现是默认显示,代码里动态判断若不支持则移除对应preference

这边官方文档提供另外一种思路,默认隐藏,动态判断支持则显示出来

 

使用自定义 SummaryProvider

无论 Preference 何时请求摘要,您都可以创建自己的 SummaryProvider,并替换 provideSummary(),以自定义摘要。 例如,下面的 EditTextPreference 展示了其作为摘要保存的值的长度:

举例来说,假设以下 EditTextPreference

<EditTextPreference
        app:key="counting"
        app:title="Counting preference"/>

onCreatePreferences() 中,新建 SummaryProvider,然后替换 provideSummary() 以返回要显示的摘要:

KotlinJava

EditTextPreference countingPreference = (EditTextPreference) findPreference("counting");

countingPreference.setSummaryProvider(new SummaryProvider<EditTextPreference>() {
    @Override
    public CharSequence provideSummary(EditTextPreference preference) {
        String text = preference.getText();
        if (TextUtils.isEmpty(text)){
            return "Not set";
        }
        return "Length of saved value: " + text.length();
    }
});

现在,Preference 摘要显示保存的值的长度,如果 不存在保存的值,则显示“未设置”。

这里有代码动态根据preference的值设定summary的方法,这块没实际用过。

 

 

首选项操作

Preference 在点按时可执行特定操作。 例如,Preference 可以用作关联应用某个单独部分的链接。 要为 Preference 添加操作,您可以直接在 Preference 上设置 Intent,或设置 OnPreferenceClickListener,以获得更具体的逻辑。

设置 Intent

您可以在 Preference 上设置 Intent,以在每次点按 Preference 时,启用新的 FragmentActivity、或单独的应用。 这等同于使用给定 IntentContext.startActivity()

您可以使用嵌套 <intent> 标签在 XML 中设置 Intent。 下方示例定义了启动 ActivityIntent

<Preference
        app:key=”activity”
        app:title="Launch activity">
    <intent
            android:targetPackage="com.example"
            android:targetClass="com.example.ExampleActivity"/>
</Preference>

或者,您也可以在 Preference 上直接使用 setIntent(),如下所示:

KotlinJava

Intent intent = new Intent(getContext(), ExampleActivity.class);
activityPreference.setIntent(intent);

您还可以通过 XML,添加带有 Intent 的 extras:

<Preference
        app:key=”activity”
        app:title="Launch activity">
    <intent
            android:targetPackage="com.example"
            android:targetClass="com.example.ExampleActivity">
        <extra
                android:name="example_key"
                android:value="example_value"/>
    </intent>
</Preference>

以下为 Preference 的示例,其中带有启动网页的 Intent

<Preference
        app:key=”webpage”
        app:title="View webpage">
    <intent
            android:action="android.intent.action.VIEW"
            android:data="http://www.google.com" />
</Preference>

KotlinJava

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.google.com"));
webpagePreference.setIntent(intent);

OnPreferenceClickListener

您可以在 Preference 上设置 OnPreferenceClickListener,当点按 Preference 时,此操作会为 onPreferenceClick() 添加回调。 例如,如果您有更复杂的逻辑可以用于处理跳转,则可以使用侦听器跳转至另一个 FragmentActivity

要设置 OnPreferenceClickListener,请使用与下方所示内容类似的代码:

KotlinJava

onClickPreference.setOnPreferenceClickListener(preference -> {
    // do something
    return true;
});

这点击事件其实没啥说的,现在Android PreferenceController都封装好了,不用单独设置了。

 

 

SharedPreferences

默认情况下,Preference 使用 SharedPreferences 保存值。 SharedPreferences API 支持从在各个应用会话中保存的文件中,读取和写入简单的键值对。

Preference Library 使用不公开的 SharedPreferences 实例,因此只有您的应用可以访问该库。

举例来说,我们假设以下 SwitchPreferenceCompat

<SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

如果用户将此开关切换至 On 状态,则 SharedPreferences 文件使用 "notifications" : "true" 键值对更新。 请注意,所用密钥与为 Preference 设置的密钥一致。

如需更多有关 SharedPreferences API 的信息,请参阅 保存键值数据

如要详细了解在 Android 上存储数据的不同方法,请参阅 数据和文件存储概览

但是实际上并不会用preference的这个特性存储值,因为Settings的preference的功能不光是Settings自己的事,更多的是服务于整个安卓系统,一般会保存到SettingsProvider中或者有特定的api接口可以设置和读取。

 

读取首选项值

要检索正在使用的 SharedPreferences 对象,请调用 PreferenceManager.getDefaultSharedPreferences()。 此方法适用于您应用的任何位置。 例如,给定一个密钥为“signature”的 EditTextPreference

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

您可以对此 Preference 的保存值进行全局检索,方法如下:

KotlinJava

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString(“signature”, "");

 

这个最近刚用到过,这个方法本质上是拼接了包名等信息生成SharedPreference的xml保存到应用目录下。

 

 

侦听首选项值的变化

要侦听 Preference 值的变化,您可以在两个接口中选择一个:

下表展示了两个接口的差别:

OnPreferenceChangeListenerOnSharedPreferenceChangeListener
针对每个首选项进行设置应用于所有首选项
在首选项要改变其保存的值时进行调用。 如果待处理的值与当前保存的值相同,则其也包括在内。只在为首选项保存的值发生变化时调用。
只通过 Preference Library 调用。 应用的单独部分可以改变保存的值。随保存值的变动进行调用,即便该值来自应用的单独部分也是如此。
在待处理的值保存前调用。在该值保存后调用。
在使用 SharedPreferencesPreferenceDataStore 时调用。只在使用 SharedPreferences 时调用。

OnPreferenceChangeListener

执行 OnPreferenceChangeListener 使您能够侦听Preference 的值将在何时出现变动。 由此,您可以验证此变动是否应该发生。 例如,以下代码展示了如何侦听密钥为“name”的 EditTextPreference 值的变化:

KotlinJava

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.e("preference", "Pending Preference value is: " + newValue);
    return true;
}

接下来,您需要直接使用 setOnPreferenceChangeListener() 设置此侦听器,如下所示:

KotlinJava

preference.setOnPreferenceChangeListener(...);

OnSharedPreferenceChangeListener

在使用 SharedPreferences 保留 Preference 值时,您还可以使用 SharedPreferences.OnSharedPreferenceChangeListener 侦听变动。 这使您能够侦听 Preference 保存的值在何时出现变动,例如在与服务器同步设置时。 以下示例展示了如何侦听密钥为“name”的 EditTextPreference 值 出现变动的时间:

KotlinJava

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals(“signature”)) {
        Log.i(TAG, “Preference value was updated to: “ + sharedPreferences.getString(key, ""));
    }
}

此外,您必须通过 registerOnSharedPreferenceChangedListener() 注册侦听器,如下所示:

KotlinJava

getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);

警告:为避免意外的垃圾回收,您必须存储对侦听器的强引用。 在您调用 registerOnSharedPreferenceChangeListener()时,SharedPreferenceManager 不会存储对侦听器的强引用。 为解决这一问题,您可直接在 PreferenceFragmentCompat 中执行 onSharedPreferenceChanged()。 您还可以创建一个实例变量,如下所示:

KotlinJava

SharedPreferences.OnSharedPreferenceChangeListener listener =
        new SharedPreferences.OnSharedPreferenceChangeListener() {...}

为妥善管理 ActivityFragment 的生命周期,您应使用 onResume()onPause() 回调完成此侦听器的注册和取消注册,如下所示:

KotlinJava

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
    super.onPause();
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

学习了下OnSharedPreferenceChangeListener的使用,可以监听preference的总体变化,但感觉没啥用。。。

 

 

使用自定义数据存储

虽然推荐使用 SharedPreferences 保留 Preference,但您也可以使用自定义数据存储。 如果您的应用将值保留至数据库,又或者值专门针对设备,这时自定义数据存储会非常有用,如示例所示。

采用数据存储

要采用自定义数据存储,先要创建一个扩展 PreferenceDataStore 的类。 以下示例创建了一个处理 String 值的数据存储:

KotlinJava

public class DataStore extends PreferenceDataStore {
    @Override
    public void putString(String key, @Nullable String value) {
        // Save the value somewhere
    }
    @Override
    @Nullable
    public String getString(String key, @Nullable String defValue) {
        // Retrieve the value
    }
}

请注意:只需替换您 Preference 对象所使用的方法。 试图调用您尚未实现的方法会导致 UnsupportedOperationException

确保不在主线程上执行任何耗时操作,以避免堵塞用户接口。 由于在保留值的过程中,包含数据存储的 FragmentActivity 可能会被销毁,所以您应该将数据序列化,以防丢失用户更改的任何值。

启用数据存储

采用数据存储后,您必须在 onCreatePreferences() 中设置新的数据存储,以便 Preference 对象使用数据存储保留值,而非使用默认的 SharedPreferences。 您可以针对每个 Preference 或整个层次结构启用数据存储。

要为特定 Preference 启用自定义数据存储,请调用 Preference 上的 setPreferenceDataStore(),如以下示例所示:

KotlinJava

Preference preference = findPreference(“key”);
preference.setPreferenceDataStore(dataStore);

要为整个层次结构启用自定义数据存储,请调用 PreferenceManager 上的 setPreferenceDataStore()

KotlinJava

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

为特定 Preference 设置的数据存储将替换为对应层次结构设置的任何数据存储。 大多数情况下,您需要为整个层次结构设置一个数据存储。

请注意:如果您在 Preference 附加到层次结构后,再为某个 Preference 设置数据存储,则 Preference 的初始值将不再传播。

这里的PreferenceDataStore看起来自定义了数据存储,但是不可避免的将一堆preference的数据存储放在了一个类里,然后可以预见到一堆if else的代码结构,没有现在Android用的PreferenceController好

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值