【起航计划 031】2015 起航计划 Android APIDemo的魔鬼步伐 30 App->Preferences->Advanced preferences 自定义preference OnPreferenceChangeListener
前篇文章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.preference.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 inflater
public 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 类型为整数,这个变量就是用来保存用户的按键次数的。
@Override
protected 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);
} @Override
protected 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来保持一些临时数据。
@Override
protected 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;
} @Override
protected 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 中。
@Override
protected 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变化时在屏幕上显示当前按键的次数:

【起航计划 031】2015 起航计划 Android APIDemo的魔鬼步伐 30 App->Preferences->Advanced preferences 自定义preference OnPreferenceChangeListener的更多相关文章
- 【起航计划 026】2015 起航计划 Android APIDemo的魔鬼步伐 25 App->Notification->Status Bar 状态栏显示自定义的通知布局,省却声音、震动
这个例子的Icons Only 和 Icons and marquee 没有什么特别好说明的. 而Use Remote views in balloon 介绍了可以自定义在Extended Statu ...
- 【起航计划 010】2015 起航计划 Android APIDemo的魔鬼步伐 09 App->Activity->Redirection 根据shared preferences是否有值决定是否redirect
Redirection示例涉及到三个Acitivity: RedirectEnter, RedirectMain,RedirectGetter. 示例的主Activity为 RedirectEnter ...
- 【起航计划 002】2015 起航计划 Android APIDemo的魔鬼步伐 01
本文链接:[起航计划 002]2015 起航计划 Android APIDemo的魔鬼步伐 01 参考链接:http://blog.csdn.net/column/details/mapdigitap ...
- 【起航计划 037】2015 起航计划 Android APIDemo的魔鬼步伐 36 App->Service->Remote Service Binding AIDL实现不同进程间调用服务接口 kill 进程
本例和下个例子Remote Service Controller 涉及到的文件有RemoteService.java ,IRemoteService.aidl, IRemoteServiceCallb ...
- 【起航计划 027】2015 起航计划 Android APIDemo的魔鬼步伐 26 App->Preferences->Preferences from XML 偏好设置界面
我们在前面的例子Android ApiDemo示例解析(9):App->Activity->Persistent State 介绍了可以使用Shared Preferences来存储一些状 ...
- 【起航计划 020】2015 起航计划 Android APIDemo的魔鬼步伐 19 App->Dialog Dialog样式
这个例子的主Activity定义在AlertDialogSamples.java 主要用来介绍类AlertDialog的用法,AlertDialog提供的功能是多样的: 显示消息给用户,并可提供一到三 ...
- 【起航计划 012】2015 起航计划 Android APIDemo的魔鬼步伐 11 App->Activity->Save & Restore State onSaveInstanceState onRestoreInstanceState
Save & Restore State与之前的例子Android ApiDemo示例解析(9):App->Activity->Persistent State 实现的UI类似,但 ...
- 【起航计划 028】2015 起航计划 Android APIDemo的魔鬼步伐 27 App->Preferences->Launching preferences 其他activity获取Preference中的值
前给例子介绍了如何使用PreferenceActivity 来显示修改应用偏好,用户对Preferences的修改自动存储在应用对应的Shared Preferences中. 本例介绍了如何从一个Ac ...
- 【起航计划 008】2015 起航计划 Android APIDemo的魔鬼步伐 07 App->Activity->Persistent State 保存状态 SharedPreferences onPause onResume
Android 提供了多种存储数据的方法,其中最简单的是使用Shared Preferences. Shared Preferences 可以存储 Key/value 对,Shared Prefere ...
随机推荐
- C#实现,一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第35位数是多少, 用递归算法实现
方法函数可以通过调用自身来进行递归.计算理论可以证明递归的作用可以完全取代循环. static void Main(string[] args) { Console.WriteLine(Ra()); ...
- Hibernate Restrictions的运算符
HQL运算符 QBC运算符 含义 = Restrictions.eq() 等于equal <> Restrictions.ne() 不等于not equal > Restrictio ...
- URAL - 1146
从来不会DP的家伙终于要开始重拾DP了 最大子矩阵没啥好说的,注意单调最大子矩阵不用这么高复杂度,另行更新 #include<bits/stdc++.h> #define rep(i,j, ...
- git平台创建项目(码云)
一.在码云创建项目 1.新建仓库 2,项目名称等 3.创建后的界面 4.克隆远程项目到本地(项目地址和用户名密码) git clone 仓库地址 注意,如果当前目录下出现git仓库同名目录时,会克隆失 ...
- 坐标&接龙型动态规划 - 20181026
109. Triangle 此题还可以用DFS,记忆化搜索去做,二刷实现 public class Solution { /** * @param triangle: a list of lists ...
- js简介 基本操作 以及循环语句 内置对象 函数044
js 全称 javascript 从交互的角度 描述行为 一 .js注释方法: //单行注释 声明变量 var 二 .声明多个变量 : var a = '2' ,b = 4, c = tru ...
- Linux 后台运行程序 和切换至前台
fg 将后台中的命令调至前台继续运行 jobs查看当前有多少在后台运行的命令 ctrl + z可以将一个正在前台执行的命令放到后台,并且暂停
- Nginx启动关闭和重启、文档直接下载不阅览
nginx启动相关 启动:sbin/nginx -c conf/nginx.conf 关闭:sbin/nginx -s stop 重启(重新加载配置文件):sbin/nginx -s reload 检 ...
- Coursera 机器学习 第5章 Neural Networks: Learning 学习笔记
5.1节 Cost Function神经网络的代价函数. 上图回顾神经网络中的一些概念: L 神经网络的总层数. sl 第l层的单元数量(不包括偏差单元). 2类分类问题:二元分类和多元分类. 上 ...
- 九度oj题目1518:反转链表
题目1518:反转链表 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:2567 解决:948 题目描述: 输入一个链表,反转链表后,输出链表的所有元素.(hint : 请务必使用链表) ...