现在的位置: 首页 > 综合 > 正文

数据存储: CheckBoxPreference

2012年08月08日 ⁄ 综合 ⁄ 共 5047字 ⁄ 字号 评论关闭

最近,做一个项目,使用 Preference 非常频繁,之前就很想写一些关于 android 数据存储的文章,这次机会来了。


先从小出着手吧,CheckBoxPreference 小巧可爱,使用简单。但是使用的时候,还是需要注意一些问题。下面开始讨论吧,欢迎拍砖!


app 运行之后,效果(很单调):




项目结构图:




这里关键是在 res/ 目录下面新建 xml 文件夹,然后新建我们需要的 Preference 布局(demo.xml)。


demo.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="Demo for checkboxpreference" >

    <CheckBoxPreference
        android:key="key_cbp"
        android:title="checkbox" 
         android:summary="this is a demo"
        android:summaryOn="open me"
        android:summaryOff="close me"
        android:persistent="false"/>

</PreferenceScreen>


代码部分,是一个继承自 PreferenceActivity 的类:

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 = "key_cbp";

    private CheckBoxPreference cbp = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.demo);

        cbp = (CheckBoxPreference) findPreference(KEY);

        cbp.setOnPreferenceClickListener(this);
        cbp.setOnPreferenceChangeListener(this);
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        Log.d("mark", "onPreferenceClick is invoked !");
        return false;
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        Log.d("mark", "onPreferenceChange is invoked !");
        return false;
    }
}


在这个类中,实现两个接口,接口方法会在点击该 CheckBoxPreference 时回调。


似乎,上面的内容没有什么很难的地方,的确!但是运行 App 之后,你会发现 CheckBox 不可以选择?!


在 API 的文档关于 onPreferenceChange 方法中有这么一句:

True to update the state of the Preference with the new value.

可以看出,在这个方法的结尾返回 true 就可以了,呵呵!这点要注意,细节决定效率嘛!


ok,再看第二个问题,我们知道 Preference 可以自动保存状态值,保存是以 xml 文件形式保存的,保存路径在 /data/data/packageName/shared_prefs/×××.xml,但是你到这个路径去找找绝对找不到?!


原因在于我们所写的 demo.xml 文件,在这个文件中,有这么一句:

android:persistent="false"

这就表示不会保存 CheckBoxPreference 这个值(是一个 boolean 值,选择上就是 true,否则就是false)了。


如果,你设置这个属性为 true,android 就会为你自动保存,看下图:



但是为什么会自动保存?为什么文件名称就是 mark.zhang_preference 呢?当然是代码决定的,看源码,就会一目了然了!


当我们点击 CheckBoxPreference 的时候,会触发事件:

protected void onClick() {
        super.onClick();
        
        boolean newValue = !isChecked();
        
        // in onBindView() an AccessibilityEventViewClickedType is sent to announce the change
        // not sending
        mSendAccessibilityEventViewClickedType = true;

        if (!callChangeListener(newValue)) {
            return;
        }
        
        setChecked(newValue);
    }


那麽,

 setChecked(newValue)

方法就可以调用,

persistBoolean(checked);

方法,该方法是 Preference 类的方法,然后调用 PreferenceManager 相关的方法获取 SharedPreference 来保存文件。


最后,看一个小问题,就是如何动态获取 CheckBoxPreerence 的值呢?很简单,实现 OnSharedPreferenceChangeListener 接口,看代码:

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 = "key_cbp";

    private CheckBoxPreference cbp = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.demo);

        cbp = (CheckBoxPreference) findPreference(KEY);

        cbp.setOnPreferenceClickListener(this);

        // 注册OnPreferenceChangeListene
        // cbp.setOnPreferenceChangeListener(this);

        // 注册 SharedPreferenceChangeListener

        // 以便回调 onSharedPreferenceChangeListener
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);

    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        Log.d("mark", "onPreferenceClick is invoked !");

        if (cbp.isChecked()) { // false
            Log.d("mark", "cbp.isChecked() = " + cbp.isChecked());
        }
        // return true;
        return false;
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        if (preference.getKey().equals(KEY)) {
            Log.d("mark", "onPreferenceChange is invoked !" + newValue); // true
        }

        // 不可以选择CheckBox
        // return false;

        // 可以选择CheckBox
        return true;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(KEY)) {
            boolean value = sharedPreferences.getBoolean(key, false);
            Log.d("mark", "onSharedPreferenceChanged is invoked !" + " and the value = " + value);
        }
    }

    @Override
    protected void onDestroy() {
        // 注销 SharedPreferenceChangeListener
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
                this);
        super.onDestroy();
    }
}


运行之后,可以看到如下打印信息:

D/mark    ( 8077): onSharedPreferenceChanged is invoked ! and the value = false
D/mark    ( 8077): onPreferenceClick is invoked !
D/mark    ( 8077): onSharedPreferenceChanged is invoked ! and the value = true
D/mark    ( 8077): onPreferenceClick is invoked !
D/mark    ( 8077): cbp.isChecked() = true


提醒一点,如果不注册onSharedPreferenceChangListener:

getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);


是不会回调 onSharedPreferenceChanged 方法的。







抱歉!评论已关闭.