作者:清醒还是迷惘_123 | 来源:互联网 | 2023-09-24 11:50
最近,做一个项目,使用 Preference 非常频繁,之前就很想写一些关于 android 数据存储的文章,这次机会来了。
先从小出着手吧,CheckBoxPreference 小巧可爱,使用简单。但是使用的时候,还是需要注意一些问题。下面开始讨论吧,欢迎拍砖!
app 运行之后,效果(很单调):
项目结构图:
这里关键是在 res/ 目录下面新建 xml 文件夹,然后新建我们需要的 Preference 布局(demo.xml)。
demo.xml 文件:
- xml version="1.0" encoding="utf-8"?>
- <PreferenceScreen xmlns:android&#61;"http://schemas.android.com/apk/res/android"
- android:title&#61;"Demo for checkboxpreference" >
-
- <CheckBoxPreference
- android:key&#61;"key_cbp"
- android:title&#61;"checkbox"
- android:summary&#61;"this is a demo"
- android:summaryOn&#61;"open me"
- android:summaryOff&#61;"close me"
- android:persistent&#61;"false"/>
-
- PreferenceScreen>
代码部分&#xff0c;是一个继承自 PreferenceActivity 的类&#xff1a;
- package mark.zhang;
-
- import android.os.Bundle;
- import android.preference.CheckBoxPreference;
- import android.preference.Preference;
- import android.preference.PreferenceActivity;
- import android.preference.Preference.OnPreferenceChangeListener;
- import android.preference.Preference.OnPreferenceClickListener;
- import android.util.Log;
-
- public class DemoActivity extends PreferenceActivity implements OnPreferenceClickListener,
- OnPreferenceChangeListener {
-
- private static final String KEY &#61; "key_cbp";
-
- private CheckBoxPreference cbp &#61; null;
-
- &#64;Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.demo);
-
- cbp &#61; (CheckBoxPreference) findPreference(KEY);
-
- cbp.setOnPreferenceClickListener(this);
- cbp.setOnPreferenceChangeListener(this);
- }
-
- &#64;Override
- public boolean onPreferenceClick(Preference preference) {
- Log.d("mark", "onPreferenceClick is invoked !");
- return false;
- }
-
- &#64;Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- Log.d("mark", "onPreferenceChange is invoked !");
- return false;
- }
- }
在这个类中&#xff0c;实现两个接口&#xff0c;接口方法会在点击该 CheckBoxPreference 时回调。
似乎&#xff0c;上面的内容没有什么很难的地方&#xff0c;的确&#xff01;但是运行 App 之后&#xff0c;你会发现 CheckBox 不可以选择&#xff1f;&#xff01;
在 API 的文档关于 onPreferenceChange 方法中有这么一句&#xff1a;
- True to update the state of the Preference with the new value.
可以看出&#xff0c;在这个方法的结尾返回 true 就可以了&#xff0c;呵呵&#xff01;这点要注意&#xff0c;细节决定效率嘛&#xff01;
ok&#xff0c;再看第二个问题&#xff0c;我们知道 Preference 可以自动保存状态值&#xff0c;保存是以 xml 文件形式保存的&#xff0c;保存路径在 /data/data/packageName/shared_prefs/×××.xml&#xff0c;但是你到这个路径去找找绝对找不到&#xff1f;&#xff01;
原因在于我们所写的 demo.xml 文件&#xff0c;在这个文件中&#xff0c;有这么一句&#xff1a;
- android:persistent&#61;"false"
这就表示不会保存 CheckBoxPreference 这个值&#xff08;是一个 boolean 值&#xff0c;选择上就是 true&#xff0c;否则就是false&#xff09;了。
如果&#xff0c;你设置这个属性为 true&#xff0c;android 就会为你自动保存&#xff0c;看下图&#xff1a;
但是为什么会自动保存&#xff1f;为什么文件名称就是 mark.zhang_preference 呢&#xff1f;当然是代码决定的&#xff0c;看源码&#xff0c;就会一目了然了&#xff01;
当我们点击 CheckBoxPreference 的时候&#xff0c;会触发事件&#xff1a;
- protected void onClick() {
- super.onClick();
-
- boolean newValue &#61; !isChecked();
-
-
-
- mSendAccessibilityEventViewClickedType &#61; true;
-
- if (!callChangeListener(newValue)) {
- return;
- }
-
- setChecked(newValue);
- }
那麽&#xff0c;
方法就可以调用&#xff0c;
方法&#xff0c;该方法是 Preference 类的方法&#xff0c;然后调用 PreferenceManager 相关的方法获取 SharedPreference 来保存文件。
最后&#xff0c;看一个小问题&#xff0c;就是如何动态获取 CheckBoxPreerence 的值呢&#xff1f;很简单&#xff0c;实现 OnSharedPreferenceChangeListener 接口&#xff0c;看代码&#xff1a;
- package mark.zhang;
-
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
- import android.os.Bundle;
- import android.preference.CheckBoxPreference;
- import android.preference.Preference;
- import android.preference.PreferenceActivity;
- import android.preference.Preference.OnPreferenceChangeListener;
- import android.preference.Preference.OnPreferenceClickListener;
- import android.util.Log;
-
- public class DemoActivity extends PreferenceActivity implements OnPreferenceClickListener,
- OnPreferenceChangeListener, OnSharedPreferenceChangeListener {
-
- private static final String KEY &#61; "key_cbp";
-
- private CheckBoxPreference cbp &#61; null;
-
- &#64;Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.demo);
-
- cbp &#61; (CheckBoxPreference) findPreference(KEY);
-
- cbp.setOnPreferenceClickListener(this);
-
-
-
-
-
-
-
- getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
-
- }
-
- &#64;Override
- public boolean onPreferenceClick(Preference preference) {
- Log.d("mark", "onPreferenceClick is invoked !");
-
- if (cbp.isChecked()) {
- Log.d("mark", "cbp.isChecked() &#61; " &#43; cbp.isChecked());
- }
-
- return false;
- }
-
- &#64;Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (preference.getKey().equals(KEY)) {
- Log.d("mark", "onPreferenceChange is invoked !" &#43; newValue);
- }
-
-
-
-
-
- return true;
- }
-
- &#64;Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (key.equals(KEY)) {
- boolean value &#61; sharedPreferences.getBoolean(key, false);
- Log.d("mark", "onSharedPreferenceChanged is invoked !" &#43; " and the value &#61; " &#43; value);
- }
- }
-
- &#64;Override
- protected void onDestroy() {
-
- getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
- this);
- super.onDestroy();
- }
- }
运行之后&#xff0c;可以看到如下打印信息&#xff1a;
- D/mark ( 8077): onSharedPreferenceChanged is invoked ! and the value &#61; false
- D/mark ( 8077): onPreferenceClick is invoked !
- D/mark ( 8077): onSharedPreferenceChanged is invoked ! and the value &#61; true
- D/mark ( 8077): onPreferenceClick is invoked !
- D/mark ( 8077): cbp.isChecked() &#61; true
提醒一点&#xff0c;如果不注册onSharedPreferenceChangListener&#xff1a;
- getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
是不会回调 onSharedPreferenceChanged 方法的。