Android中删除Preference详解
android的设置界面实现比较简单,有时甚至只需要使用一个简单的xml文件即可.声明简单,但是如何从preferencescreen或者preferencecategory中删除一个preference会简单么.为什么有些人写的就无法删除成功呢?本文将从android源码实现来分析一下.
声明文件
<?xml version="1.0" encoding="utf-8"?>
<preferencescreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="root">
<preferencecategory
android:key="theme"
android:title="theme"
android:summary="theme settings"
>
<checkboxpreference
android:key="holo_theme"
android:title="holo theme"
android:summary="use holo theme"
/>
</preferencecategory>
<checkboxpreference
android:key="rmcache"
android:title="auto clear cache"
android:summary="enable auto clear cache "
/>
</preferencescreen>
层级关系
删除preference
删除key为rmcache的preference,这个preference是preferencescreen root的子节点.
preferencescreen screen = getpreferencescreen();
checkboxpreference autoclearcheckboxpref = (checkboxpreference) screen.findpreference("rmcache");
screen.removepreference(autoclearcheckboxpref);
删除key为holo_theme的preference,其为preferencescreen root的孙子节点,非直接关系.
preferencecategory themeprefcategory = (preferencecategory) screen.findpreference("theme");
checkboxpreference holocheckboxpref = (checkboxpreference)themeprefcategory.findpreference("holo_theme");
themeprefcategory.removepreference(holocheckboxpref);
为什么删除失败
很多人出现了删除失败的问题,主要原因是使用了非父亲节点来删除,比如这样
preferencescreen screen = getpreferencescreen();
checkboxpreference holocheckboxpref = (checkboxpreference)screen.findpreference("holo_theme");
screen.removepreference(holocheckboxpref);
preferencegroup删除实现,其实preferencescreen和preferencecategory都是preferencegroup的子类.
/**
* removes a {@link preference} from this group.
*
* @param preference the preference to remove.
* @return whether the preference was found and removed.
*/
public boolean removepreference(preference preference) {
final boolean returnvalue = removepreferenceint(preference);
notifyhierarchychanged();
return returnvalue;
}
private boolean removepreferenceint(preference preference) {
synchronized(this) {
preference.onprepareforremoval();
return mpreferencelist.remove(preference);
}
}
而mpreferencelist中存放的都是当前preferencegroup的直接子preference.
findpreference实现
findpreference查找不仅仅限于直接子preference,会遍历其所有的子preference.
所以代码中同样有root preferencegroup和直接父preferencegroup引用时,通常后者效率会高.
/**
* finds a {@link preference} based on its key. if two {@link preference}
* share the same key (not recommended), the first to appear will be
* returned (to retrieve the other preference with the same key, call this
* method on the first preference). if this preference has the key, it will
* not be returned.
* <p>
* this will recursively search for the preference into children that are
* also {@link preferencegroup preferencegroups}.
*
* @param key the key of the preference to retrieve.
* @return the {@link preference} with the key, or null.
*/
public preference findpreference(charsequence key) {
if (textutils.equals(getkey(), key)) {
return this;
}
final int preferencecount = getpreferencecount();
for (int i = 0; i < preferencecount; i++) {
final preference preference = getpreference(i);
final string curkey = preference.getkey();
if (curkey != null && curkey.equals(key)) {
return preference;
}
if (preference instanceof preferencegroup) {
final preference returnedpreference = ((preferencegroup)preference)
.findpreference(key);
if (returnedpreference != null) {
return returnedpreference;
}
}
}
return null;
}
findpreference和removepreference实现比较
为什么findpreference遍历所有的子节点,而removepreference不会,只会删除直接子preference
原因有以下几点:
1.findpreference支持遍历查找,减少了声明诸多的中间preferencegroup代码.而findpreference属于常用接口方法.
2.removepreference调用较少.
3.当存在key相同的preference时,如果removepreference不限定直接子preference,那么无法准确删除哪一个.
上一篇: 记住心急吃不了热豆腐