在CursorAdapter中为可见视图传递相同的convertView实例

时间:2013-03-05 19:54:56

标签: java android listview simplecursoradapter

我在android中自定义创建的CursorAdapter派生类有一个奇怪的问题:

我的getView()实现是在许多网站/ Google会谈中看到的直接教科书。但是,似乎对于不同的位置(这个方法被调用的位置参数),这个方法正在传递 convertView 的相同实例,即使我看到它,这些应该引用不同的对象实例,因为它应该对应于ListView中的其他可见项,并且在可见列表项的情况下不应该重用相同的对象实例...

我删除了更新实际视图的实际部分,因为即使没有它也会重现问题。

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        Log.d("dd", "getView()");

        if (convertView == null) {
            Log.d("d", "convertview is null!");

            // create convertView from xml
            convertView = this.mInflater.inflate(R.layout.catalog_entry,
                    parent, false);

            // create the viewHolder
            viewHolder = new ViewHolder();

            viewHolder.name = (TextView) convertView
             .findViewById(R.id.gameName2);
             viewHolder.image = (ImageView) convertView
             .findViewById(R.id.gameImage);

            convertView.setTag(viewHolder);
        } else {
            Log.d("dd", "convertview is not null");
            viewHolder = (ViewHolder) convertView.getTag();
        }

        LinearLayout thisItem = (LinearLayout) convertView;
        Log.d("thisItem",
                "This Item is Index "
                        + position
                        + " "
                        + thisItem.toString()
                        + " "
                        + Integer.toHexString(System.identityHashCode(thisItem))
                        + "x: " + thisItem.getX() + " y: " + thisItem.getY());

        this.cur.moveToPosition((int) (getItemId(position) - 1));

        Log.d("dd", "End of getView()");
        return convertView;
    }

运行此代码会产生以下输出:

  

D / dd(27725):getView()D / d(27725):convertview为null!   D / thisItem(27725):此项目为索引0   android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()的结束D / dd(27725):getView()D / dd
  (27725):convertview不为空D / thisItem(27725):此项目为索引   1 android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()的结束D / dd(27725):getView()D / dd
  (27725):convertview不为空D / thisItem(27725):此项目为索引   2 android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()的结束D / dd(27725):getView()D / dd
  (27725):convertview不为空D / thisItem(27725):此项目为索引   3 android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()的结束D / dd(27725):getView()D / dd
  (27725):convertview不为空D / thisItem(27725):此项目为索引   4 android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()的结束D / dd(27725):getView()D / dd
  (27725):convertview不为空D / thisItem(27725):此项目为索引   0 android.widget.LinearLayout@40fb5f70 40fb5f70x:0.0 y:0.0 D / dd
  (27725):getView()结束D / dd(27725):getView()D / d
  (27725):convertview为null! D / thisItem(27725):此项目为索引1   android.widget.LinearLayout@40fb89f8 40fb89f8x:0.0 y:0.0 D / dd
  (27725):getView()结束D / dd(27725):getView()D / d
  (27725):convertview为null! D / thisItem(27725):此项目为索引2   android.widget.LinearLayout@40fb9c48 40fb9c48x:0.0 y:0.0 D / dd
  (27725):getView()结束D / dd(27725):getView()D / d
  (27725):convertview为null! D / thisItem(27725):此项目为索引3   android.widget.LinearLayout@40fbae98 40fbae98x:0.0 y:0.0 D / dd
  (27725):getView()结束D / dd(27725):getView()D / d
  (27725):convertview为null! D / thisItem(27725):此项目为索引4   android.widget.LinearLayout@40fbc0e8 40fbc0e8x:0.0 y:0.0 D / dd
  (27725):getView()的结束

从一开始就可以看出,对于每个位置(0到4),都会发送相同的View对象哈希......

2 个答案:

答案 0 :(得分:4)

简而言之,将ListView的高度设置为match_parent或其他固定高度。

ListView以“干运行”方式调用getView()的原因有很多,最常见的是因为您使用了wrap_content作为ListView的高度。 Android必须为一堆行充气以计算wrap_content的高度,但它不能使用真实数据,因为它尚不可用。因此,适配器会抛出这些最佳猜测。稍后,使用实际数据(重新)创建布局,这就是为什么您看到每行创建两次。

CursorAdapter也应该自己维护相应的行,你不需要这一行:

this.cur.moveToPosition((int)(getItemId(position) - 1));

答案 1 :(得分:1)

Convertview重用视图是正确的。 您可以删除所有Convertview部分,并确保它不会重复使用不需要的视图,您将获得所需的结果(以某些性能为代价......)。