Here is my custom 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.
The ViewHolder design pattern enables you to access each list item view without the need for the look up, saving valuable processor cycles. Specifically, it avoids frequent call of findViewById() during ListView scrolling, and that will make it smooth.
ViewHolder design pattern is used to speed up rendering of your ListView - actually to make it work smoothly. Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance.
A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results.
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 love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With