在自定义CursorAdapter中正确实现的ViewHolder模式?

这是我的自定义CursorAdapter:

public class TasksAdapter extends CursorAdapter implements Filterable { private final Context context; public TasksAdapter(Context context, Cursor c) { super(context, c); this.context = context; } /** * @see android.widget.CursorAdapter#newView(android.content.Context, android.database.Cursor, android.view.ViewGroup) */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(android.R.layout.simple_list_item_checked, parent, false); ViewHolder holder = new ViewHolder(); holder.textview = (CheckedTextView)v.findViewById(android.R.id.text1); v.setTag(holder); return v; } /** * @see android.widget.CursorAdapter#bindView(android.view.View, android.content.Context, android.database.Cursor) */ @Override public void bindView(View view, Context context, Cursor cursor) { ViewHolder holder = (ViewHolder)view.getTag(); int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE); int completedCol = cursor.getColumnIndexOrThrow(Tasks.COMPLETED); String title = cursor.getString(titleCol); boolean completed = Util.intToBool(cursor.getInt(completedCol)); holder.textview.setText(title); holder.textview.setChecked(completed); } /** * @see android.widget.CursorAdapter#runQueryOnBackgroundThread(java.lang.CharSequence) */ @Override public Cursor runQueryOnBackgroundThread(CharSequence constraint) { StringBuffer buffer = null; String[] args = null; if (constraint != null) { buffer = new StringBuffer(); buffer.append("UPPER ("); buffer.append(Tasks.TITLE); buffer.append(") GLOB ?"); args = new String[] { "*" + constraint.toString().toUpperCase() + "*" }; } Cursor c = context.getContentResolver().query(Tasks.CONTENT_URI, null, (buffer == null ? null : buffer.toString()), args, Tasks.DEFAULT_SORT_ORDER); c.moveToFirst(); return c; } /** * @see android.widget.CursorAdapter#convertToString(android.database.Cursor) */ @Override public CharSequence convertToString(Cursor cursor) { final int titleCol = cursor.getColumnIndexOrThrow(Tasks.TITLE); String title = cursor.getString(titleCol); return title; } static class ViewHolder { CheckedTextView textview; } } 

这是否落入ViewHolder模式的约束? 我不确定,因为这是一个CursorAdapter,没有getView 。 如果有任何问题或build议,请把它们指出来。

Solutions Collecting From Web of "在自定义CursorAdapter中正确实现的ViewHolder模式?"

每次需要新行时, CursorAdapter都不会调用newView ; 如果它已经有一个View ,它将调用bindView ,所以创build的视图实际上被重用。

也就是说,正如Joseph在评论中指出的那样,您仍然可以使用ViewHolder来避免重复调用findViewById

如果您仍然关心效率问题,那么请查看SimpleCursorAdapter实现,该实现使用WeakHashMapWeakReferences一个映射):

 WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>(); 

如果你重载newView()bindView() ,你不需要做任何额外的getView()CursorAdapter具有getView()的实现,该实现委托newView()bindView()来强制行回收。

findViewById()可能会在ListView的滚动过程中频繁调用,这会降低性能。 即使Adapter返回一个膨胀的视图来回收,仍然需要查找元素并进行更新。 为了避免这种情况, ViewHolder模式很有用。

以下是为天气应用程序实施的ViewHolder模式示例:

 public class ForecastAdapter extends CursorAdapter { public ForecastAdapter(Context context, Cursor cursor, int flags) { super(context, cursor, flags); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = LayoutInflater.from(context).inflate( R.layout.list_item_forecast, parent, false); ViewHolder viewHolder = new ViewHolder(view); view.setTag(viewHolder); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { ViewHolder viewHolder = (ViewHolder) view.getTag(); long date = cursor.getLong(ForecastFragment.COL_WEATHER_DATE); viewHolder.dateView.setText("Today"); String weatherForecast = cursor.getString(ForecastFragment.COL_WEATHER_DESC); viewHolder.descriptionView.setText(weatherForecast); double high = cursor.getFloat(ForecastFragment.COL_WEATHER_MAX_TEMP); viewHolder.highTempView.setText("30"); double low = cursor.getFloat(ForecastFragment.COL_WEATHER_MIN_TEMP); viewHolder.lowTempView.setText("24"); int weatherConditionId = cursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID); viewHolder.iconView.setImageResource(R.drawable.ic_snow); } /** Cache of the children views for a list item. */ public static class ViewHolder { public final ImageView iconView; public final TextView dateView; public final TextView descriptionView; public final TextView highTempView; public final TextView lowTempView; public ViewHolder(View view) { iconView = (ImageView) view.findViewById(R.id.item_icon); dateView = (TextView) view.findViewById(R.id.item_date_textview); descriptionView = (TextView) view.findViewById(R.id.item_forecast_textview); highTempView = (TextView) view.findViewById(R.id.item_high_textview); lowTempView = (TextView) view.findViewById(R.id.item_low_textview); } } } 

我的一个类的实现扩展了SimpleCursorAdapter与newViewbindView但没有ViewHolder模式

  private class CountriesAdapter extends SimpleCursorAdapter { private LayoutInflater mInflater; public CountriesAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to, LayoutInflater inflater) { super(getActivity(), layout, cursor, from, to, CURSOR_ADAPTER_FLAGS); mInflater = inflater; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { return mInflater.inflate(R.layout.countries_list_row, parent, false); } @Override public void bindView(View rowView, Context context, Cursor cursor) { TextView tvCountry = (TextView) rowView.findViewById(R.id.countriesList_tv_countryName); TextView tvOrgs = (TextView) rowView.findViewById(R.id.countriesList_tv_orgNames); ImageView ivContinent = (ImageView) rowView.findViewById(R.id.countriesList_iv_continentName); // TODO: set texts of TextViews and an icon here } } }