zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

Android中删除Preference详解

Android 详解 删除 preference
2023-06-13 09:15:40 时间

Android的设置界面实现比较简单,有时甚至只需要使用一个简单的xml文件即可.声明简单,但是如何从PreferenceScreen或者PreferenceCategory中删除一个Preference会简单么.为什么有些人写的就无法删除成功呢?本文将从Android源码实现来分析一下.

声明文件

复制代码代码如下:


<?xmlversion="1.0"encoding="utf-8"?>
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"
   android:key="root">

 <PreferenceCategory
     android:key="theme"
     android:title="Theme"
     android:summary="ThemeSettings"
     >
     <CheckBoxPreference
         android:key="holo_theme"
         android:title="HoloTheme"
         android:summary="UseHoloTheme"
         />
     
 </PreferenceCategory>
 
 <CheckBoxPreference
     android:key="rmcache"
     android:title="AutoClearCache"
     android:summary="EnableAutoClearCache"
     />
</PreferenceScreen>

层级关系

删除Preference

删除key为rmcache的Preference,这个Preference是PreferenceScreenroot的子节点.

复制代码代码如下:


PreferenceScreenscreen=getPreferenceScreen();
CheckBoxPreferenceautoClearCheckboxPref=(CheckBoxPreference)screen.findPreference("rmcache");
screen.removePreference(autoClearCheckboxPref);

删除key为holo_theme的Preference,其为PreferenceScreenroot的孙子节点,非直接关系.

复制代码代码如下:
PreferenceCategorythemePrefCategory=(PreferenceCategory)screen.findPreference("theme");
CheckBoxPreferenceholoCheckboxPref=(CheckBoxPreference)themePrefCategory.findPreference("holo_theme");
themePrefCategory.removePreference(holoCheckboxPref);

为什么删除失败

很多人出现了删除失败的问题,主要原因是使用了非父亲节点来删除,比如这样

复制代码代码如下:
PreferenceScreenscreen=getPreferenceScreen();
CheckBoxPreferenceholoCheckboxPref=(CheckBoxPreference)screen.findPreference("holo_theme");
screen.removePreference(holoCheckboxPref);

PreferenceGroup删除实现,其实PreferenceScreen和PreferenceCategory都是PreferenceGroup的子类.

复制代码代码如下:
/**
    *Removesa{@linkPreference}fromthisgroup.
    *
    *@parampreferenceThepreferencetoremove.
    *@returnWhetherthepreferencewasfoundandremoved.
    */
   publicbooleanremovePreference(Preferencepreference){
       finalbooleanreturnValue=removePreferenceInt(preference);
       notifyHierarchyChanged();
       returnreturnValue;
   }

   privatebooleanremovePreferenceInt(Preferencepreference){
       synchronized(this){
           preference.onPrepareForRemoval();
           returnmPreferenceList.remove(preference);
       }
   }

而mPreferenceList中存放的都是当前PreferenceGroup的直接子Preference.

findPreference实现

findPreference查找不仅仅限于直接子Preference,会遍历其所有的子Preference.

所以代码中同样有rootPreferenceGroup和直接父PreferenceGroup引用时,通常后者效率会高.

复制代码代码如下:
/**
 *Findsa{@linkPreference}basedonitskey.Iftwo{@linkPreference}
 *sharethesamekey(notrecommended),thefirsttoappearwillbe
 *returned(toretrievetheotherpreferencewiththesamekey,callthis
 *methodonthefirstpreference).Ifthispreferencehasthekey,itwill
 *notbereturned.
 *<p>
 *Thiswillrecursivelysearchforthepreferenceintochildrenthatare
 *also{@linkPreferenceGroupPreferenceGroups}.
 *
 *@paramkeyThekeyofthepreferencetoretrieve.
 *@returnThe{@linkPreference}withthekey,ornull.
 */
publicPreferencefindPreference(CharSequencekey){
   if(TextUtils.equals(getKey(),key)){
       returnthis;
   }
   finalintpreferenceCount=getPreferenceCount();
   for(inti=0;i<preferenceCount;i++){
       finalPreferencepreference=getPreference(i);
       finalStringcurKey=preference.getKey();

       if(curKey!=null&&curKey.equals(key)){
           returnpreference;
       }

       if(preferenceinstanceofPreferenceGroup){
           finalPreferencereturnedPreference=((PreferenceGroup)preference)
                   .findPreference(key);
           if(returnedPreference!=null){
               returnreturnedPreference;
           }
       }
   }

   returnnull;
}

findPreference和removePreference实现比较

为什么findPreference遍历所有的子节点,而removePreference不会,只会删除直接子Preference

原因有以下几点:

1.findPreference支持遍历查找,减少了声明诸多的中间PreferenceGroup代码.而findPreference属于常用接口方法.
2.removePreference调用较少.
3.当存在key相同的Preference时,如果removePreference不限定直接子Preference,那么无法准确删除哪一个.