tutorial recyclerview que personalizado create adapters java android adapter

java - recyclerview - ¿El patrón ViewHolder implementado correctamente en el CursorAdapter personalizado?



recyclerview adapter android (3)

Mi implementación de una clase extiende SimpleCursorAdapter con newView y bindView pero sin el patrón 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 } } }

Aquí está mi CursorAdapter personalizado:

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; } }

¿Esto cae dentro de las restricciones del patrón ViewHolder? No estaba seguro porque esto era un CursorAdapter, donde no había getView . Si hay algún problema o sugerencia, puede indicarlos.


Si está anulando newView() y bindView() , no necesita hacer nada extra en getView() . CursorAdapter tiene una implementación de getView() que delega a newView() y bindView() para forzar el reciclaje de filas.

findViewById() puede llamarse frecuentemente durante el desplazamiento de ListView , lo que puede ralentizar el rendimiento. Incluso cuando el Adapter devuelve una vista inflada para el reciclaje, aún debe buscar los elementos y actualizarlos. Para evitar esto, el patrón ViewHolder es útil.

Aquí hay un ejemplo del patrón de ViewHolder implementado para una aplicación meteorológica:

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); } } }


CursorAdapter no llamará a newView cada vez que necesite una nueva fila; si ya tiene una View , llamará a bindView , por lo que la vista creada se reutilizará.

Dicho esto, como lo señaló Joseph en los comentarios, aún puede usar ViewHolder para evitar llamar a findViewById repetidamente.

Si aún está preocupado por la eficiencia, eche un vistazo a la implementación de SimpleCursorAdapter , que utiliza un WeakHashMap (un mapa de WeakReferences ):

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