Getview VS. Bindview in a Custom Cursoradapter

GetView Vs. BindView in a custom CursorAdapter?

CursorAdapter has an implementation of getView() that delegates to newView() and bindView(), in such a way as enforces the row recycling pattern. Hence, you do not need to do anything special with a CursorAdapter for row recycling if you are overriding newView() and bindView().

Android CursorAdapter getView / newView should be inflate same things?

Implementing getView() or the newView()/bindView() group is the same thing in terms of performance and you should choose the later option. For Cursor based adapters the getView() method is implemented so it uses the view recycling mechanism along with delegating the row construction to the newView()(build the views of the row) and bindView()(bind the data to the rows) methods. It also moves the Cursor to the correct position.

Also, as njzk2 , pointed out you should set the data on the view in the bindView() method. The newView() method will not be called for every row of the ListView, it will be called only for the case when there isn't a recycled row already available, that's why you should only build the row view in newView(). The bindView() method, however, will be called each time and here's where you should bind the data from the Cursor to the row views.

What bindView() and newView() do in CursorAdapter

In order to understand this, you must first understand how BaseAdapter works, since CursorAdapter is a subclass of BaseAdapter.

Android maintains a pool of views for a ListView which it will give to you so you can reuse it instead of creating a new view each time.

In BaseAdapter, you will have a function called getView(), to which one of the parameters is a View object named convertView. Basically, this convertView will be null if the list is being loaded for the first time, and it will not be null once you start sliding the list. Therefore, in the getView() method of your BaseAdapter, you will check if convertView is null. If yes, you will inflate it. Then you can use the view and set its elements as normal. This will improve the scrolling performance of a listview tremendously.

A CursorAdapter makes it easy to use when the data source of a listview is a database. In a cursor adapter, however, Android takes care of checking whether the convertView is null or not. In the newView() method, you simply inflate the view and return it. In the bindView() method, you set the elements of your view.

As an example, imagine a listview on a device which can show upto 11 list items on the screen. In this case, newView() will be called upto 11 times. However, bindView() will be called many times whenever you scroll the list view. The 11 views you created in your newView method will be reused again and again as you scroll the list.

get a position in bindView using CursorAdapter

For This first you need to override getView() and set the position here and access it in bindview() later.

@Override
public View getView(int position, View convertview, ViewGroup arg2) {
if (convbertview == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertview = inflater.inflate(R.layout.your layout,
null);
}
convertview.setTag(position);
return super.getView(position, convbertview, arg2);
}

and in bindView() get your position like

@Override
public void bindView(View view, Context context, Cursor cursor) {
int position=(Integer) view.getTag();//here is the position

}

ViewHolder pattern correctly implemented in custom CursorAdapter?

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

CursorAdapter inconsistent between newView and bindView

By default, ListView (and any other source that takes a CursorAdapter tries to reuse views as often as possible.

Therefore newView() is called only until enough views are created and after that, only bindView() is called as you scroll down the list as it reuses the views it has already created.

If you have multiple view types (as it seems you do), you should also override getViewTypeCount() and getItemViewType(). These methods tell the adapter that only views of the same type should be reused, ensuring that your rows using listrow_chat_me are only used for future listrow_chat_me rows and not reused for listrow_chat_other rows.

@Override
public int getViewTypeCount() {
return 2;
}

@Override
public int getItemViewType(int position) {
// getItem(position) returns a Cursor at the given position
Cursor cursor = (Cursor) getItem(position);
if (cursor.getInt(cursor.getColumnIndexOrThrow(DbChat.KEY_SENDER_ID)) == 0) {
return 0;
} else {
return 1;
}
}

Issues with a ListView and a custom cursorAdapter

you have not return view from getView() method. current you return null value .that's why you get null pointer exception call newview inside getView() and return appropriate view .

for more info read below SO Question

What bindView() and newView() do in CursorAdapter

Android: Issue with newView and bindView in custom SimpleCursorAdapter

Overriding the getView() function gives you the possibility of "re-using" already inflated list items (the list items that are "scrolled out" from the current view port when you scroll your list back and forth).

By doing so you'll save a lot of memory resources and processor run time, since inflating is a quite time consuming operation. For each and every convertView you re-use you also save GC run-time (since the garbage collector doesn't have to collect that specific list item).

You can also create a "view collection" class (the ViewHolder class in the below example) which will hold the references for each view in your inflated list item. This way you don't have to find them each and every time you update a list item with new values (typically whan you scroll the list). findViewById() is also a rather time consuming operation.

Also I think you can cache more variables, like the layout inflater, and the column indices. Everything to save time :-)

private final Context mContext;
private final int mLayout;
private final Cursor mCursor;
private final int mNameIndex;
private final int mIdIndex;
private final LayoutInflater mLayoutInflater;

private final class ViewHolder {
public TextView name;
public ImageView image;
public CheckBox checkBox;
}

public FriendAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);

this.mContext = context;
this.mLayout = layout;
this.mCursor = c;
this.mNameIndex = mCursor.getColumnIndex(WhipemDBAdapter.KEY_NAME);
this.mIdIndex = mCursor.getColumnIndex(WhipemDBAdapter.KEY_FB_ID);
this.mLayoutInflater = LayoutInflater.from(mContext);
}

public View getView(int position, View convertView, ViewGroup parent) {
if (mCursor.moveToPosition(position)) {
ViewHolder viewHolder;

if (convertView == null) {
convertView = mLayoutInflater.inflate(mLayout, null);

viewHolder = new ViewHolder();
viewHolder.name = (TextView) convertView.findViewById(R.id.contact_name);
viewHolder.image = (ImageView) convertView.findViewById(R.id.contact_pic);
viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);

convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}

String name = mCursor.getString(mNameIndex);
String fb_id = mCursor.getString(mIdIndex);
Drawable drawable = LoadImageFromWebOperations("http://graph.facebook.com/"+fb_id+"/picture");
boolean isChecked = ((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id);

viewHolder.name.setText(name);
viewHolder.image.setImageDrawable(drawable);
viewHolder.checkBox.setTag(fb_id);
viewHolder.checkBox.setChecked(isChecked);
}

return convertView;
}

Android - How to get position in bindView like in getView?

Try this

public void bindView(View arg0, Context arg1, Cursor arg2)
{
int pos = arg2.getPosition();
}


Related Topics



Leave a reply



Submit