【问题标题】:Android: getView() called twice in custom adapterAndroid:getView() 在自定义适配器中调用了两次
【发布时间】:2011-03-08 08:42:01
【问题描述】:

我正在将自定义 SimpleCursorAdapter 设置为 ListView。出于某种原因,对于数据库中的每个项目,FriendAdapter 的 getView() 都会被调用两次。经过一番调查(我的contact_list.xml中没有wrap_content),我仍然无法弄清楚原因。

可能是什么原因?有人可以帮忙吗?

谢谢

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>

【问题讨论】:

    标签: android listview adapter


    【解决方案1】:

    这是正常的,当您有一个带有height=wrap_content(以及其他)的列表视图时可能会发生:

    看最后一个帖子:http://groups.google.com/group/android-developers/browse_thread/thread/4c4aedde22fe4594

    【讨论】:

    • 我的列表视图没有 height=wrap_content。我还应该不担心吗?获取/设置我行中所有值的两倍似乎是无用的重复处理。
    • 正如链接所说 - 这是正常的,不用担心。
    • 是的,我也遇到过。似乎是正常的行为。但是,如果您仅根据位置 ID 在 getView() 中运行代码,则有时可以避免这种情况。不过,这有点骇人听闻。
    • “别担心。”,这确实给我带来了很多难以调试的不良行为。很高兴我找到了这篇文章!
    • 我认为我们应该担心适配器是否占用大量资源。就我而言,这也是一个问题。
    【解决方案2】:

    我用过这个。 getView 运行两次,但如果你检查convertView 是否为null,里面的代码将运行一次。

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

    【讨论】:

      【解决方案3】:

      对我来说,视图似乎是用相同的方法创建了两次。一个在“if(convertView==null)”中,另一个在“else”中。如果我在其中一次 if 语句中什么都不做,那么它只会创建一次。似乎该方法本身只被调用了一次。

      【讨论】:

        【解决方案4】:

        为了每行只调用一次getView,您需要调用super.getView,然后更改返回的视图。是这样的

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-24
          • 1970-01-01
          • 1970-01-01
          • 2013-04-21
          • 2018-06-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多