前篇文章Android ApiDemo示例解析(31):App->Preferences->Launching preferences 中用到了Advanced preferences 中定义的AdvancedPreferences。

本篇具体介绍AdvancedPreferences, 这个例子称为Advanced ,是因为它涉及到了自定义Preference, 并在一个工作线程中刷新某个Preference的值。

Preference 为显示在PreferenceActivity (一般以列表显示)在某个偏好的基类。有点类似于显示在Activity中的某个View。Preference 实际存取的是对应在Shared Preferences中一项,而Preference定义的key也就是用来访问Shared Preferences的key值。

和View一样可以自定义View,在Android中也可以自定义Preference,用来显示管理应用自定义的程序偏好。本例 MyPreference 自定义一个Preference 用来存储用户点击该Preference的次数,类型为整数,初始值定义为100。它在advanced_preferences.xml 对应的定义如下:

<com.example.android.apis.app.MyPreference
android:key=”my_preference”

android:title=”@string/title_my_preference”
android:summary=”@string/summary_my_preference”
android:defaultValue=”100″ />

Preference 定义了很多属性,比如Default Value, dependency, enabled, icon ,key 等等都有对应的方法来操作。并且提供了两个Listener:PreferenceChangeListener, PreferenceClickListener ,允许应用程序响应Preference值变化事件,或是用户点击Preference事件。

这里按照MyPreference 代码顺序说明一下如何自定义一个Preference。

1. 派生于 Preference基类。

public class MyPreference extends Preference


2. 和自定义View类似可以为自定义Preference 自定义Layout。 MyPreference 使用R.layout.preference_widget_mypreference ,定义很简单只有一个TextView ,其id为mypreference_widget。 一般在构造函数中使用setWidgetLayoutResource为Preference派生类设置Layout资源。

// This is the constructor called by the inflaterpublic MyPreference(Context context, AttributeSet attrs) { super(context, attrs);  setWidgetLayoutResource(R.layout.preference_widget_mypreference);}


3. 如有需要为自定义的Layout中的View 设置属性,可以在onBindView(View view)中完成。下面代码为TextView设置值为mClickCounter。

@Override protected void onBindView(View view) { super.onBindView(view);  // Set our custom views inside the layout final TextView myTextView = (TextView) view.findViewById(R.id.mypreference_widget); if (myTextView != null) { myTextView.setText(String.valueOf(mClickCounter)); } }


4. 如果为该自定义Preference 在XML定义了初值,比如 MyPreference的初值android:defaultValue=”100″,我们想在代码中使用这个初值来初始化变量mClickCounter 。mClickCounter 类型为整数,这个变量就是用来保存用户的按键次数的。

@Overrideprotected Object onGetDefaultValue(TypedArray a, int index) { // This preference type's value type is Integer, so we read the default // value from the attributes as an Integer. return a.getInteger(index, 0);} @Overrideprotected void onSetInitialValue(boolean restoreValue, Object defaultValue) { if (restoreValue) { // Restore state mClickCounter = getPersistedInt(mClickCounter); } else { // Set state int value = (Integer) defaultValue; mClickCounter = value; persistInt(value); }}


5 重载 onSaveInstanceState,onRestoreInstanceState ,这两个方法是用来临时保存或是恢复一些变量值。在Preference 调用persistInt,persistBoolean, persistString等之前,preference 对应的值还没有被保存在或是更新在Shared preferences 中,如果这时用户旋转屏幕,则造成Activity重新创建,我们需要在屏幕旋转时用户选择项会保留,可以使用onSaveInstanceState,onRestoreInstanceState来保持一些临时数据。

@Overrideprotected Parcelable onSaveInstanceState() { /* * Suppose a client uses this preference type without persisting. We * must save the instance state so it is able to, for example, survive * orientation changes. */  final Parcelable superState = super.onSaveInstanceState(); if (isPersistent()) { // No need to save instance state since it's persistent return superState; }  // Save the instance state final SavedState myState = new SavedState(superState); myState.clickCounter = mClickCounter; return myState;} @Overrideprotected void onRestoreInstanceState(Parcelable state) { if (!state.getClass().equals(SavedState.class)) { // Didn't save state for us in onSaveInstanceState super.onRestoreInstanceState(state); return; }  // Restore the instance state SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); mClickCounter = myState.clickCounter; notifyChanged();}


其中SavedState为BaseSavedState的子类,这里不详细介绍了,而BaseSavedState实现了Parcelable接口,借用Windows平台上的Serialable,其功能和其它平台上序列化功能类似。

6. MyPreference响应Click事件,并将按键次数存入Shared Preferences 中。

@Overrideprotected void onClick() { int newValue = mClickCounter + 1; // Give the client a chance to ignore this change if they deem it // invalid if (!callChangeListener(newValue)) { // They don't want the value to be set return; }  // Increment counter mClickCounter = newValue;  // Save to persistent storage (this method will make sure this // preference should be persistent, along with other useful checks) persistInt(mClickCounter);  // Data has changed, notify so UI can be refreshed! notifyChanged();}


Preference使用persistBoolean, persistFloat ,persistInt, persistLong ,persisitString 向Shared Preferences中存储数据,因为mClickCounter为整数,所以使用persistInt。 notifyChanged用于通知UI有数据变化。callChangeListener 将会调用注册过的Preference.OnPreferenceChangeListener 以通知Preference有变化。

再来看看AdvancedPreferences,代码不是很长,如下:

public class AdvancedPreferences extends PreferenceActivity implements OnSharedPreferenceChangeListener { public static final String KEY_MY_PREFERENCE = "my_preference"; public static final String KEY_ADVANCED_CHECKBOX_PREFERENCE = "advanced_checkbox_preference";  private CheckBoxPreference mCheckBoxPreference; private Handler mHandler = new Handler();  /** * This is a simple example of controlling a preference from code. */ private Runnable mForceCheckBoxRunnable = new Runnable() { public void run() { if (mCheckBoxPreference != null) { mCheckBoxPreference .setChecked(!mCheckBoxPreference.isChecked()); }  // Force toggle again in a second mHandler.postDelayed(this, 1000); } };  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);  // Load the XML preferences file addPreferencesFromResource(R.xml.advanced_preferences);  // Get a reference to the checkbox preference mCheckBoxPreference = (CheckBoxPreference)getPreferenceScreen() .findPreference(KEY_ADVANCED_CHECKBOX_PREFERENCE); }  @Override protected void onResume() { super.onResume();  // Start the force toggle mForceCheckBoxRunnable.run();  // Set up a listener whenever a key changes getPreferenceScreen() .getSharedPreferences() .registerOnSharedPreferenceChangeListener(this); }  @Override protected void onPause() { super.onPause();  // Unregister the listener whenever a key changes getPreferenceScreen() .getSharedPreferences() .unregisterOnSharedPreferenceChangeListener(this);  mHandler.removeCallbacks(mForceCheckBoxRunnable); }  public void onSharedPreferenceChanged( SharedPreferences sharedPreferences, String key) { // Let's do something when my counter preference value changes if (key.equals(KEY_MY_PREFERENCE)) { Toast.makeText(this, "Thanks! You increased my count to " + sharedPreferences.getInt(key, 0), Toast.LENGTH_SHORT).show(); } } }


它实现了OnSharedPreferenceChangeListener,因此可以用来监听MyPreference的变化。

Handler ,由于程序中需要从工作线程中更新Preference的值,而Preference为UI,不可以从工作线程中直接更新UI,Handler允许工作线程来更新UI,后续有详细介绍。本例每隔1秒将Haunted preference 值变化一次(选中->不选->选中->不选 ..)

registerOnSharedPreferenceChangeListener,unregisterOnSharedPreferenceChangeListener用来为SharedPreferences 注册一个总的Preference 变化事件处理代码。本例中MyPreference变化时在屏幕上显示当前按键的次数:

Preferences->Advanced preferences_第1张图片" src="https://img.it610.com/image/info5/a4939feb9b9f409fb8f71f48cde545ef.jpg" width="344" height="501" style="border:1px solid black;">

更多相关文章

  1. android 支持的资源类型及其存放的目录
  2. android 自定义注解处理器
  3. 自定义带提示的文本输入框
  4. 转:ANDROID音频系统散记之四:4.0音频系统HAL初探
  5. Android(安卓)Camera 运行流程
  6. Android(安卓)炫酷的自定义进度条ProgressBar集锦,优雅呈现
  7. Android基于zxing-android-embedded实现自定义扫码界面,连续扫码
  8. Android开发之自定义Notification(源代码分享)
  9. Android(安卓)RoboGuice 使用指南(14):Inject View

随机推荐

  1. 超简单理解Android四大组件
  2. Android性能测试工具--Oprofile
  3. android studio用Javah创建.h头文件和编
  4. Android(安卓)kotlin网络请求框架fuel(简
  5. Android中在屏幕上涂鸦的例子
  6. Android(安卓)WebView常见问题及解决方案
  7. Android(安卓)调用系统相机返回data为nul
  8. Android(安卓)解决离线路由GraphHopper
  9. Android(安卓)Studio 真机调试vivo系列手
  10. Appium环境搭建教程