java 在自定义 CursorAdapter 中正确实现了 ViewHolder 模式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4567969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ViewHolder pattern correctly implemented in custom CursorAdapter?
提问by Mohit Deshpande
Here is my custom CursorAdapter:
这是我的自定义 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;
}
}
Does this fall into the constraints of the ViewHolder pattern? I wasn't sure because this was a CursorAdapter, where there was no getView
. If there are any problems or suggestions, could you please point them out.
这是否属于 ViewHolder 模式的约束?我不确定,因为这是一个 CursorAdapter,没有getView
. 如果有任何问题或建议,请您指出。
回答by Cristian
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.
CursorAdapter
newView
每次需要新行时都不会调用;如果它已经有一个View
,它会调用bindView
,所以创建的视图实际上会被重用。
That said, as pointed out by Josephin the comments, you can still use ViewHolder in order to avoid calling findViewById
repeatedly.
也就是说,正如约瑟夫在评论中指出的那样,您仍然可以使用 ViewHolder 以避免findViewById
重复调用。
If you are still concerned about efficiency then take a look at the SimpleCursorAdapter
implementation, which uses a WeakHashMap
(a map of WeakReferences
):
如果您仍然关心效率,请查看SimpleCursorAdapter
使用WeakHashMap
(的映射WeakReferences
)的实现:
WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>();
回答by Yogesh Umesh Vaity
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.
如果您覆盖newView()
and bindView()
,则无需在getView()
. CursorAdapter
具有getView()
委托newView()
并bindView()
强制执行行回收的实现。
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.
findViewById()
可能会在 滚动期间频繁调用ListView
,这会降低性能。即使Adapter
返回一个膨胀的视图以供回收,您仍然需要查找元素并更新它们。为了避免这种情况,ViewHolder
模式很有用。
Here's an example of ViewHolder
pattern implemented for a weather app:
这是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);
}
}
}
回答by Maksim Dmitriev
My implementation of a class extends SimpleCursorAdapter with newView
and bindView
but without the ViewHolder
pattern
我的一个类的实现扩展了 SimpleCursorAdapter 有newView
和bindView
没有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
}
}
}