欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android中删除Preference详解

程序员文章站 2022-03-23 14:07:04
android的设置界面实现比较简单,有时甚至只需要使用一个简单的xml文件即可.声明简单,但是如何从preferencescreen或者preferencecategor...

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>

层级关系

Android中删除Preference详解

删除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,那么无法准确删除哪一个.