Merge change Ia98129b9 into eclair-mr2

* changes:
  Fix preference caching to increase recycling of preference views.
This commit is contained in:
Android (Google) Code Review
2009-10-07 15:01:25 -04:00
2 changed files with 72 additions and 38 deletions

View File

@@ -188,17 +188,7 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Preference);
if (a.hasValue(com.android.internal.R.styleable.Preference_layout) ||
a.hasValue(com.android.internal.R.styleable.Preference_widgetLayout)) {
// This preference has a custom layout defined (not one taken from
// the default style)
mHasSpecifiedLayout = true;
}
a.recycle();
a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Preference,
defStyle, 0);
com.android.internal.R.styleable.Preference, defStyle, 0);
for (int i = a.getIndexCount(); i >= 0; i--) {
int attr = a.getIndex(i);
switch (attr) {
@@ -252,6 +242,11 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
}
}
a.recycle();
if (!getClass().getName().startsWith("android.preference")) {
// For subclasses not in this package, assume the worst and don't cache views
mHasSpecifiedLayout = true;
}
}
/**
@@ -332,11 +327,11 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* @see #setWidgetLayoutResource(int)
*/
public void setLayoutResource(int layoutResId) {
if (!mHasSpecifiedLayout) {
if (layoutResId != mLayoutResId) {
// Layout changed
mHasSpecifiedLayout = true;
}
mLayoutResId = layoutResId;
}
@@ -360,6 +355,10 @@ public class Preference implements Comparable<Preference>, OnDependencyChangeLis
* @see #setLayoutResource(int)
*/
public void setWidgetLayoutResource(int widgetLayoutResId) {
if (widgetLayoutResId != mWidgetLayoutResId) {
// Layout changed
mHasSpecifiedLayout = true;
}
mWidgetLayoutResId = widgetLayoutResId;
}

View File

@@ -69,7 +69,9 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
* count once--when the adapter is being set). We will not recycle views for
* Preference subclasses seen after the count has been returned.
*/
private List<String> mPreferenceClassNames;
private ArrayList<PreferenceLayout> mPreferenceLayouts;
private PreferenceLayout mTempPreferenceLayout = new PreferenceLayout();
/**
* Blocks the mPreferenceClassNames from being changed anymore.
@@ -86,14 +88,37 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
}
};
private static class PreferenceLayout implements Comparable<PreferenceLayout> {
private int resId;
private int widgetResId;
private String name;
public int compareTo(PreferenceLayout other) {
int compareNames = name.compareTo(other.name);
if (compareNames == 0) {
if (resId == other.resId) {
if (widgetResId == other.widgetResId) {
return 0;
} else {
return widgetResId - other.widgetResId;
}
} else {
return resId - other.resId;
}
} else {
return compareNames;
}
}
}
public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
mPreferenceGroup = preferenceGroup;
// If this group gets or loses any children, let us know
mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
mPreferenceList = new ArrayList<Preference>();
mPreferenceClassNames = new ArrayList<String>();
mPreferenceLayouts = new ArrayList<PreferenceLayout>();
syncMyPreferences();
}
@@ -102,7 +127,7 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
if (mIsSyncing) {
return;
}
mIsSyncing = true;
}
@@ -128,7 +153,7 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
preferences.add(preference);
if (!mHasReturnedViewTypeCount) {
if (!mHasReturnedViewTypeCount && !preference.hasSpecifiedLayout()) {
addPreferenceClassName(preference);
}
@@ -143,15 +168,28 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
}
}
/**
* Creates a string that includes the preference name, layout id and widget layout id.
* If a particular preference type uses 2 different resources, they will be treated as
* different view types.
*/
private PreferenceLayout createPreferenceLayout(Preference preference, PreferenceLayout in) {
PreferenceLayout pl = in != null? in : new PreferenceLayout();
pl.name = preference.getClass().getName();
pl.resId = preference.getLayoutResource();
pl.widgetResId = preference.getWidgetLayoutResource();
return pl;
}
private void addPreferenceClassName(Preference preference) {
final String name = preference.getClass().getName();
int insertPos = Collections.binarySearch(mPreferenceClassNames, name);
final PreferenceLayout pl = createPreferenceLayout(preference, null);
int insertPos = Collections.binarySearch(mPreferenceLayouts, pl);
// Only insert if it doesn't exist (when it is negative).
if (insertPos < 0) {
// Convert to insert index
insertPos = insertPos * -1 - 1;
mPreferenceClassNames.add(insertPos, name);
mPreferenceLayouts.add(insertPos, pl);
}
}
@@ -171,19 +209,15 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
public View getView(int position, View convertView, ViewGroup parent) {
final Preference preference = this.getItem(position);
if (preference.hasSpecifiedLayout()) {
// If the preference had specified a layout (as opposed to the
// default), don't use convert views.
// Build a PreferenceLayout to compare with known ones that are cacheable.
mTempPreferenceLayout = createPreferenceLayout(preference, mTempPreferenceLayout);
// If it's not one of the cached ones, set the convertView to null so that
// the layout gets re-created by the Preference.
if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0) {
convertView = null;
} else {
// TODO: better way of doing this
final String name = preference.getClass().getName();
if (Collections.binarySearch(mPreferenceClassNames, name) < 0) {
convertView = null;
}
}
return preference.getView(convertView, parent);
}
@@ -225,8 +259,9 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
return IGNORE_ITEM_VIEW_TYPE;
}
final String name = preference.getClass().getName();
int viewType = Collections.binarySearch(mPreferenceClassNames, name);
mTempPreferenceLayout = createPreferenceLayout(preference, mTempPreferenceLayout);
int viewType = Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout);
if (viewType < 0) {
// This is a class that was seen after we returned the count, so
// don't recycle it.
@@ -242,7 +277,7 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
mHasReturnedViewTypeCount = true;
}
return Math.max(1, mPreferenceClassNames.size());
return Math.max(1, mPreferenceLayouts.size());
}
}