Android: Issue with newView and bindView in custom SimpleCursorAdapter

荒凉一梦 提交于 2019-11-27 11:30:13

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;
}
Romain Guy

The example is almost right. You don't need to do the binding in newView(), since like you mentioned, bindView() will be called. If you see the sequence newView/bindView called twice per item, you are probably using ListView with its height set to wrap_content, which is always a bad idea. Finally, newView() and bindView() are specific to CursorAdapter: it implements getView() and calls either newView() or bindView() for you. However, overriding getView() is perfectly valid as well. This is how other adapters work.

Note that getView() (and therefore bindView/newView) are only invoked for each item that will be displayed on the screen.

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