ViewHolder模式中setTag和getTag的工作原理是什么?

Fen*_*nil 12 android listview android-adapter android-viewholder

我有一个简单的代码片段来实现自定义列表视图.

我的代码如下:

WeatherAdapter.java:

public class WeatherAdapter extends ArrayAdapter<weather>{

    Context mcontext; 
    int mlayoutResourceId;    
   weather mdata[] = null;
   View row;

    public WeatherAdapter(Context context, int layoutResourceId, weather[] data) {
        super(context, layoutResourceId, data);
        mlayoutResourceId = layoutResourceId;
       mcontext = context;
        mdata = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      row = convertView;
        WeatherHolder holder = null;

        if(row == null)
        {
            LayoutInflater inflater = ( (Activity) mcontext).getLayoutInflater();
            row = inflater.inflate(mlayoutResourceId, parent, false);

            holder = new WeatherHolder(row);


            row.setTag(holder);

        }
        else
        {
            holder = (WeatherHolder)row.getTag();
        }

        weather w = mdata[position];
        holder.txtTitle.setText(w.mtitle);
        holder.imgIcon.setImageResource(w.micon);

        return row;
    }
Run Code Online (Sandbox Code Playgroud)

WeatherHolder.java:

class WeatherHolder
    {
        ImageView imgIcon;
        TextView txtTitle;


    public WeatherHolder(View v){

          imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
          txtTitle = (TextView)row.findViewById(R.id.txtTitle);

    }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在SO和其他网站上看到了很多答案,我理解了listview的回收机制.

我也明白,从viewholder,我们可以在适配器中保存子视图,我们不必findViewById()多次调用.所以,它是为了优化.

但我只有混乱setTag(holder)getTag()方法.从这个问题开始,我开始知道它是为多个对象创建一个键值对,以便我们可以轻松访问它们.但是,我不明白为什么在这里需要它们...因为,我们没有多个持有者对象......只是我们每次都要改变持有者的变量.我们可以在这里编码而不使用setTaggetTag

任何人都可以更好地解释什么setTaggetTag做"在这里"?

mml*_*loo 24

tag是一种机制,让您views想起了什么,这可能是一个objectinteger一个string或任何你喜欢的.

所以当你ListView第一次创造你convertView的时候null.所以你创建一个新的convertView,并把所有的referencesobjectsrow一个viewHolder.然后将你保存viewHolder到那个convertView(setTag)的记忆中.Android拿走你的东西convertView并把它放在它poolrecycle里面,passes它再次给你.但它pool可能没有足够的convertViews,因此再次通过新的convertView多数民众赞成null.如此反复重复的故事,直到poolandroid被填满.之后从池中android拿出一个convertView并传递给你.你会发现它不是null那么你问我references第一次给你的对象在哪里?(getTag)所以你会得到那些并做你喜欢的事.

下面详细说明

but its pool may not have enough convertViews so it again passes a new convertView thats null

pool当你listView要创建时,android 是空的.因此,对于您的第一项,listView它会向您发送convertView必须显示的项目.之后android将其保存在其中pool,因此它pool现在只包含一个convertView.你的第二项listView是将要创建的Android,因为它实际上是有一个元素和元素是你的第一个项目,它正在显示现在所以它必须通过另一个不能使用它的游泳池convertView.这个过程重复进行,直到android发现convertViewpool现在没有显示并传递给你.

当你滚动使用持有者的列表时,Android会对每一行进行充气,直到屏幕填满为止.


nef*_*tou 17

让我们看一个不同的视角:

在此输入图像描述

让我们想象直升机是" ",而绳索是" setTag ",下面的是" WeatherHolder ",但是直升机的飞行员在那辆车内,他/她是管理直升机的人"有线遥控".

当你切断绳索"setTag"时,Hellicopter仍然会飞,但飞行员无法控制它,因为飞行员在地面上掉落,这意味着飞行员现在已经死了!(在java中,当一个对象丢失它的引用时,垃圾收集器将收集该内容并从内存中释放出来).

当直升机即将飞行在飞行员所在的位置时,您没有将绳索放置或连接到汽车上 - 由于您正在使用"有线远程",您可能会失去对直升机的控制.

我希望这有帮助:).