jul
jul

Reputation: 37464

Android: getView() called twice in custom adapter

I'm setting a custom SimpleCursorAdapter to a ListView. For some reason FriendAdapter's getView() is called twice for every item in the DB. After some investigation (I have no wrap_content in my contact_list.xml), I can still not figure out why.

What could be the reasons? Anybody can help?

Thanks

ContactSelection.java

public class ContactSelection extends ListActivity {

    private WhipemDBAdapter mDbHelper;  

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mDbHelper = new WhipemDBAdapter(this);
        mDbHelper.open();     

        setContentView(R.layout.contact_list);        

        Cursor c = mDbHelper.fetchAllFriends();
        startManagingCursor(c);     
        String[] from = new String[] {};
        int[] to = new int[] {};

        setListAdapter(new FriendAdapter(this, R.layout.contact_row, c, from, to));

        getListView().setItemsCanFocus(false);
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mDbHelper.open();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mDbHelper.close();
    }
}

FriendAdapter.java

public class FriendAdapter extends SimpleCursorAdapter implements OnClickListener {

    private Context mContext;
    private int mLayout;
    private Cursor mCursor;
    private int mNameIndex;
    private int mIdIndex;
    private LayoutInflater mLayoutInflater; 
    private final ImageDownloader imageDownloader = new ImageDownloader();  

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

    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);
                viewHolder.checkBox.setOnClickListener(this);

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

            String name = mCursor.getString(mNameIndex);
            String fb_id = mCursor.getString(mIdIndex);         
            boolean isChecked = ((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id);

            viewHolder.name.setText(name);
            imageDownloader.download("http://graph.facebook.com/"+fb_id+"/picture", viewHolder.image);

            viewHolder.checkBox.setTag(fb_id);
            viewHolder.checkBox.setChecked(isChecked);
        }

        return convertView;
    }

    @Override
    public void onClick(View v) {
        CheckBox cBox = (CheckBox) v;
        String fb_id = (String) cBox.getTag();

        if (cBox.isChecked()) {
            if (!((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
                ((GlobalVars) mContext.getApplicationContext()).addSelectedFriend(fb_id);
        } else {
            if (((GlobalVars) mContext.getApplicationContext()).isFriendSelected(fb_id))
                ((GlobalVars) mContext.getApplicationContext()).removeSelectedFriend(fb_id);
        }

    }
}

contact_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/contact_pic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/contact_name"        
        android:textSize="10sp"
        android:singleLine="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <CheckBox
        android:id="@+id/checkbox"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

contact_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
    <ListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    <TextView
        android:id="@+id/android:empty"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="No items"/>
</LinearLayout>

Upvotes: 15

Views: 17812

Answers (4)

user2064635
user2064635

Reputation: 61

I used this. The getView runs twice, but if you check if convertView is null, the code inside will be run once.

public View getView(int position, View convertView, ViewGroup parent) {
    View superView = super.getView(position, convertView, parent);
    if (convertView == null)
    {
         // Customize superView here

    }
    return superView;
}

Upvotes: 4

user5130224
user5130224

Reputation: 1

For me it seems like the view is created twice in the same method. One in "if(convertView==null)" and the other "else". If I did nothing in once of the if statements then it is only created once. It seems like the method itself is only called once though.

Upvotes: 0

gmauri21
gmauri21

Reputation: 7

In order to getView get call only once for each row, you need to call super.getView and then change the returned view. It's something like this

public View getView(int position, View convertView, ViewGroup parent) {
    View superView = super.getView(position, convertView, parent);
    if (mCursor.moveToPosition(position)) {
         // Customize superView here

    }
    return superView;
}

Upvotes: -1

Peter Knego
Peter Knego

Reputation: 80340

This is normal and can happen when you have a listview with height=wrap_content (among others):

Look at the last post: http://groups.google.com/group/android-developers/browse_thread/thread/4c4aedde22fe4594

Upvotes: 12

Related Questions