Skip to content Skip to sidebar Skip to footer

Viewholder Pattern Correctly Implemented In Custom Cursoradapter?

Here is my custom CursorAdapter: public class TasksAdapter extends CursorAdapter implements Filterable { private final Context context; public TasksAdapter(Context contex

Solution 1:

CursorAdapter won't call the newView each time it needs a new row; if it already has a View, it will call the bindView, so the created view is actually reused.

That said, as pointed out by Joseph in the comments, you can still use ViewHolder in order to avoid calling findViewById repeatedly.

If you are still concerned about efficiency then take a look at the SimpleCursorAdapter implementation, which uses a WeakHashMap (a map of WeakReferences):

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

Solution 2:

If you are overriding newView() and bindView(), you don't need to do anything extra in getView(). CursorAdapter has an implementation of getView() that delegates to newView() and bindView() to enforce the row recycling.

findViewById() maybe called frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. To avoid this, ViewHolder pattern is useful.

Here's an example of ViewHolder pattern implemented for a weather app:

publicclassForecastAdapterextendsCursorAdapter {

    publicForecastAdapter(Context context, Cursor cursor, int flags) {
        super(context, cursor, flags);
    }

    @Overridepublic View newView(Context context, Cursor cursor, ViewGroup parent) {
        Viewview= LayoutInflater.from(context).inflate(
                R.layout.list_item_forecast, parent, false);
        ViewHolderviewHolder=newViewHolder(view);
        view.setTag(viewHolder);
        return view;
    }

    @OverridepublicvoidbindView(View view, Context context, Cursor cursor) {
        ViewHolderviewHolder= (ViewHolder) view.getTag();

        longdate= cursor.getLong(ForecastFragment.COL_WEATHER_DATE);
        viewHolder.dateView.setText("Today");

        StringweatherForecast=
                cursor.getString(ForecastFragment.COL_WEATHER_DESC);
        viewHolder.descriptionView.setText(weatherForecast);

        doublehigh= cursor.getFloat(ForecastFragment.COL_WEATHER_MAX_TEMP);
        viewHolder.highTempView.setText("30");

        doublelow= cursor.getFloat(ForecastFragment.COL_WEATHER_MIN_TEMP);
        viewHolder.lowTempView.setText("24");

        intweatherConditionId=
                cursor.getInt(ForecastFragment.COL_WEATHER_CONDITION_ID);
        viewHolder.iconView.setImageResource(R.drawable.ic_snow);
    }

    /** Cache of the children views for a list item. */publicstaticclassViewHolder {
        publicfinal ImageView iconView;
        publicfinal TextView dateView;
        publicfinal TextView descriptionView;
        publicfinal TextView highTempView;
        publicfinal TextView lowTempView;

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

Solution 3:

My implementation of a class extends SimpleCursorAdapter with newView and bindView but without the ViewHolder pattern

privateclassCountriesAdapterextendsSimpleCursorAdapter {

            private LayoutInflater mInflater;

            publicCountriesAdapter(Context context, int layout, Cursor cursor, String[] from,
                    int[] to, LayoutInflater inflater) {
                super(getActivity(), layout, cursor, from, to, CURSOR_ADAPTER_FLAGS);
                mInflater = inflater;
            }

            @Overridepublic View newView(Context context, Cursor cursor, ViewGroup parent) {
                return mInflater.inflate(R.layout.countries_list_row, parent, false);
            }

            @OverridepublicvoidbindView(View rowView, Context context, Cursor cursor) {

                TextViewtvCountry= (TextView) rowView.findViewById(R.id.countriesList_tv_countryName);
                TextViewtvOrgs= (TextView) rowView.findViewById(R.id.countriesList_tv_orgNames);
                ImageViewivContinent=
                        (ImageView) rowView.findViewById(R.id.countriesList_iv_continentName);

                // TODO: set texts of TextViews and an icon here
                }

            }
    }

Post a Comment for "Viewholder Pattern Correctly Implemented In Custom Cursoradapter?"