一、获取SharedPreferences实例
1.1、指定名称的SharedPreferences
Context.getSharedPreferences(String name, int mode)
由于Activity中已经存在Context的实例,所以在Activity中可以直接通过getSharedPreferences(String, int)获取SharedPreferences的实例
参数说明
name:SharedPreferences存储的文件名,如果name不存在,则会在Editor.commit()后创建
mode:创建模式,值为0或者其他的值,我们一般填0应用内访问就可以了,详情查看
1.2、获取默认的SharedPreferences
PreferenceManager.getDefaultSharedPreferences(Context context)
我这里用的是android.support.v7.preference库,使用的时候需要在App gradle中配置dependencies
如下图所示
代码如下
implementation 'com.android.support:preference-v7:28.0.0'
二、编辑和删除数据
2.1、获取编辑器
SharedPreferences.edit(),获取SharedPreferences.Editor的实例
2.2、赋值
字符串赋值:putString(String key, String value)
2.3、标记删除所有数据
clear()
2.3、提交
提交有一下两种方式,修改数据完成后需要执行提交的方法才会完成修改
(1)、apply()
(2)、commit()
SharedPreferences.Editor更多的使用方法参考链接
三、查看数据
查看数据是基于SharedPreferences的实例进行操作
如:getString(String key, String defValue)
更多查看方式链接
四、静态资源引用
4.1、字符串静态资源引用
这里用到的key字符串与及其它字符串默认值建议使用引用静态资源的方式赋值,详情参考链接
注意,在使用静态资源赋值到key时,需要设置translatable属性为false,防止国际化等其它原因导致key值被转换,设置如下所示:
<string name="pref_size_key" translatable="false">size</string>
4.2、布尔值静态资源引用
布尔类型的默认值建议也是用资源引用的方式赋值,详情参考链接
五、监听SharedPreferences的数据被修改
5.1、实现接口
在需要监听的类里面实现SharedPreferences.OnSharedPreferenceChangeListener接口
比如在Activity中实现接口SharedPreferences.OnSharedPreferenceChangeListener,实现接口的方法onSharedPreferenceChanged
比如下面的实现代码:
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(“signature”)) {
Log.i(TAG, “Preference value was updated to: “ + sharedPreferences.getString(key, ""));
}
}
5.2、注册监听
通过SharedPreferences的registerOnSharedPreferenceChangeListener方法注册一个监听器
@Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
5.3、取消监听
如果注册了监听,则需要在退出的时候取消注册监听:
@Override
public void onPause() {
super.onPause();
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
需要注意的是,我前面注册的是默认的SharedPreferences,所以取消注册的时候我也是先获取的默认的SharedPreferences。
5.4、参考
六、偏好设置实例
6.1、PreferenceFragmentCompat
其实还有对应的activity的实现,但是谷歌官方推荐使用Fragment,使用更灵活。
在fragment中继承PreferenceFragmentCompat,实现方法onCreatePreferences,从xml资源文件中添加preferences:
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.pref_visualizer);
}
pref_visualizer资源文件如下
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="@bool/pref_show_bass_default"
android:key="@string/pref_show_bass_key"
android:summaryOff="@string/hidden"
android:summaryOn="@string/show"
android:title="@string/show_base_label" />
<CheckBoxPreference
android:defaultValue="@bool/pref_show_mid_default"
android:key="@string/pref_show_mid_key"
android:summaryOff="@string/hidden"
android:summaryOn="@string/show"
android:title="@string/show_mid_label" />
<CheckBoxPreference
android:defaultValue="@bool/pref_show_treble_default"
android:key="@string/pref_show_treble_key"
android:summaryOff="@string/hidden"
android:summaryOn="@string/show"
android:title="@string/show_treble_label" />
<EditTextPreference
android:defaultValue="@string/pref_size_default"
android:key="@string/pref_size_key"
android:title="@string/setting_size_label"/>
<ListPreference
android:defaultValue="@string/pref_color_red_value"
android:entries="@array/pref_color_option_labels"
android:entryValues="@array/pref_color_option_values"
android:key="@string/pref_color_key"
android:title="@string/selector_color" />
</PreferenceScreen>
这里的EditTextPreference和ListPreference默认没有描述值,需要在代码中添加描述
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.pref_visualizer);
PreferenceScreen preferenceScreen = getPreferenceScreen();
SharedPreferences sharedPreferences = preferenceScreen.getSharedPreferences();
int count = preferenceScreen.getPreferenceCount();
for (int i = 0; i < count; i++) {
Preference preference = preferenceScreen.getPreference(i);
if (!(preference instanceof CheckBoxPreference)) {
String value = sharedPreferences.getString(preference.getKey(), getString(R.string.pref_color_red_value));
setupPreferenceSummary(preference, value);
}
}
Preference preference = findPreference(getString(R.string.pref_size_key));
preference.setOnPreferenceChangeListener(this);
}
private void setupPreferenceSummary(Preference preference, String s) {
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int position = listPreference.findIndexOfValue(s);
if (position >= 0) {
listPreference.setSummary(listPreference.getEntries()[position]);
}
} else if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference) preference;
editTextPreference.setSummary(s);
}
}
监听EditTextPreference和ListPreference的值修改后,更新描述内容
在fragment的onCreate方法中注册监听器,需要先在fragment中implements SharedPreferences.OnSharedPreferenceChangeListener
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
设置EditTextPreference和ListPreference的值修改后显示正确的描述内容
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference preference = findPreference(key);
if (null != preference) {
if (!(preference instanceof CheckBoxPreference)) {
String value = sharedPreferences.getString(preference.getKey(), getString(R.string.pref_color_red_value));
setupPreferenceSummary(preference, value);
}
}
}
别忘了要在onDestroy方法中取消注册:
@Override
public void onDestroy() {
super.onDestroy();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
注意,我们这里用到了EditTextPreference,因为我这里希望只获取float类型的值,如果用户输入其它类型的值,会在赋值的时候导致类型异常报错,所以我们要在修改Preference值之前先对用户输入的内容进行判断处理。
为了解决这个问题,我们可以在fragment中implements Preference.OnPreferenceChangeListener,然后实现对应的onPreferenceChange方法,onPreferenceChange方法实现如下,如果用户输入我们期待的数据类型,则return true,否则return false:
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Toast error = Toast.makeText(getContext(), "Please select a number between 0.1 and 3", Toast.LENGTH_SHORT);
String sizeKey = getString(R.string.pref_size_key);
if (preference.getKey().equals(sizeKey)) {
String stringSize = ((String) (newValue)).trim();
if (stringSize.equals("")) stringSize = "1";
try {
float size = Float.parseFloat(stringSize);
if (size > 3 || size <= 0) {
error.show();
return false;
}
} catch (NumberFormatException nfe) {
error.show();
return false;
}
}
return true;
}
设置修改Preference前的回调,该监听不需要在退出的时候取消注册,通过对比方法名可以看出,这里是set方法,不是register:
Preference preference = findPreference(getString(R.string.pref_size_key));
preference.setOnPreferenceChangeListener(this);
注意,使用PreferenceFragmentCompat需要在application的主题中添加属性,否则在打开引用PreferenceFragmentCompat的页面会报错:
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
此外,PreferenceScreen还可以设置偏好类别和通过代码code的方式引入PreferenceScreen而不仅仅是通过xml的方式引入,更多相关内容可以查看官方用户指南链接