Preference小结

 

1.framework/base/core/java/android/preference/Preference.java
从代码可以看到,对于某个Preference被click后,会先检查该preference的mOnClickListener是否为空,
如果不为空,则调用并返回。
否则,调用该preference所在的PreferenceManager.OnPreferenceTreeClickListener,
(Called when a preference in the tree rooted at this PreferenceScreen has been clicked.)
如果还为空,则启动该preference设置的intent activity。

    /*
    
Called when a click should be performed.
    
    
@param preferenceScreen A {@link PreferenceScreen} whose hierarchy click
                 listener should be called in the proper order (between other
    
            processing). May be null.
     */
    void performClick(PreferenceScreen preferenceScreen) {
        
        if (!isEnabled()) {
            return;
        }
        
        onClick();
        
        if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
            return;
        }
        
        PreferenceManager preferenceManager = getPreferenceManager();
        if (preferenceManager != null) {
            PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
                    .getOnPreferenceTreeClickListener();
            if (preferenceScreen != null && listener != null
                    && listener.onPreferenceTreeClick(preferenceScreen, this)) {
                return;
            }
        }
        
        if (mIntent != null) {
            Context context = getContext();
            context.startActivity(mIntent);
        }
    }
    

2.performClick()何时被调用?
PreferenceScreen中包含一个ListAdapter,所有的Preference都对应该adapter中的一项。
该Adapter是一个PreferenceGroupAdapter,当PreferenceScreen中的某项被点击后,
onItemClick()被调用,接着调用preference的performClick()。

 

具体流程如下:

PreferenceActivity继承自ListActivity,启动时会调用onContentChanged,
onContentChanged() > postBindPreference() > mHandler >
bindPreference():
得到当前的preferenceScreen和当前activity的listview >
preferenceScreen.bind(getListView())
PreferenceScreen.java:
    public void bind(ListView listView) {
        listView.setOnItemClickListener(this);
        listView.setAdapter(getRootAdapter());
        
        onAttachedToActivity();
    }
设置了listview的onItemClickListener,
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        Object item = getRootAdapter().getItem(position);
        if (!(item instanceof Preference)) return;
        
        final Preference preference = (Preference) item;
       preference.performClick(this);
    }


3.onPreferenceChange()何时被调用?
在Prefercen子类(如CheckBoxPreference)的onClick()函数中,会调用callChangeListener(),
(Preference的onClick()函数注释: Processes a click on the preference. This includes saving the value to the SharedPreferences.
However, the overridden method should call callChangeListener(Object) to make sure the client
wants to update the preference’s state with the new value.)
callChangeListener调用用户自己设置的onChangeListener:
    protected boolean callChangeListener(Object newValue) {
        return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue);
    }

perference还有一个OnPreferenceChangeInternalListener,它是在PreferenceGroupAdapter在
flattenPreferenceGroup()时设置的:
preference.setOnPreferenceChangeInternalListener(this);
当CheckBoxPreference调用setTitle、setSummary、setEnabled等时,会调用notifyChanged(),
    protected void notifyChanged() {
        if (mListener != null) {
            mListener.onPreferenceChange(this);
        }
    }
进而调用PreferenceGroupAdapter的:
    public void onPreferenceChange(Preference preference) {
        notifyDataSetChanged();
    }



4.PreferenceCategory实际上就是一个PreferenceGroup,也是一个始终处于disabled状态的Preference。
(Used to group Preference objects and provide a disabled title above the group.)
它的isEnabled()函数始终返回false:
    @Override
    public boolean isEnabled() {
        return false;
    }