在使用视图持有者时,listView中行的回收如何工作?

时间:2017-06-16 05:52:25

标签: java android listview android-viewholder

我为ListView行定义了一个ViewHolder,如下所示:

->joinField('qty','cataloginventory/stock_item','qty','product_id=entity_id','{{table}}.is_in_stock=1','left')

并且适配器类的import android.view.View; import android.widget.ImageView; import android.widget.TextView; class ViewHolder { ImageView icon=null; TextView size=null; ViewHolder(View row) { this.icon=(ImageView)row.findViewById(R.id.icon); this.size=(TextView)row.findViewById(R.id.size); } } 方法如下所示:

getView()

现在我的问题是:

  1. @Override public View getView(int position, View convertView, ViewGroup parent) { View row=super.getView(position, convertView, parent); ViewHolder holder=(ViewHolder)row.getTag(); if (holder==null) { holder=new ViewHolder(row); row.setTag(holder); } if (getModel(position).length()>4) { holder.icon.setImageResource(R.drawable.delete); } else { holder.icon.setImageResource(R.drawable.ok); } holder.size.setText(String.format(getString(R.string.size_template), items[position].length())); return(row); } 调用View的情况下,在什么情况下会返回null?

  2. getTag()做了什么以及如何重新初始化ViewHolder?

  3. 如何在ListView中回收视图,以及row.setTag(holder)getTag()在使用适配器时如何帮助我们?

  4. 我对工作机制有点困惑,并且在没有找到任何结果的情况下搜索了Stack Overflow。

1 个答案:

答案 0 :(得分:1)

这是一个非常好的问题。为了了解适配器中Tags的行为,我们需要知道listView中循环过程流的实际行为。

Tag是一个小工具,可让我们的views记住一些东西,可能是一个对象,一个整数或其他任何东西,所以当我们的ListView第一次创建时该时间convertViewnull,因此我们创建了一个新的convertView,并将row objects的所有引用放在viewHolder中,然后将viewHolder保存到convertViewsetTag)的内存中。 Android接受我们的convertView并将其放入池内存中以回收它并将其再次传递给我们。但是它的池内存可能不够convertViews,因此它再次传递convertView null。所以故事再次重复,直到android池充满为止。之后android从其池中获取convertView并将其传递给我们。你会发现它不是null,所以你问它我第一次使用getTag()给你的对象引用在哪里,这样你就可以得到那些并做你喜欢的事。

这是列表ViewHolder的流程,但如果你想了解更多关于setTag()和getTag()的信息,我会给你一个例子:

假设您正在创建具有类似行为的一堆视图,如:

button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );

然后你将覆盖方法onClick(),如:

private void onClick(View view) {
    doAction(0); // here 0 for button 1 and 1 for button 2. 
}

这是因为在onclick()方法中只有一个参数View,你可以使用setTag()来改变它的行为,使用值'0'和'1'来访问不同的按钮: 只需添加

button1.setTag(0);
button2.setTag(1);

现在,您可以通过使用函数getTag()获取附加到View的标记,为每个按钮使用相同的OnClickListener:

listener = new OnClickListener() {
    @Override
    public void onClick(View view) {
        doAction(view.getTag());
    }
};

这是因为您使用setTag()方法将视图放入池内存中,然后相应地从池中获取这些视图。