ViewHolder pattern correctly implemented in custom CursorAdapter?

廉价感情. 提交于 2019-11-27 18:46:33

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[]>();

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:

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

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

    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
                }

            }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!