Android ViewHolder 模式中 setTag 和 getTag 的作用是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25966689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:52:51  来源:igfitidea点击:

What is the working of setTag and getTag in ViewHolder pattern?

androidlistviewandroid-adapterandroid-viewholder

提问by xyz

I have a simple code snippet for implementing custom listview.

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

My code is as follows:

我的代码如下:

WeatherAdapter.java :

天气适配器.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;
    }

WeatherHolder.java:

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

    }
    }
}

I have seen so many answers on SO and other sites and I understood the recycling mechanism of listview.

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

I also understood that from viewholder, we can hold the child views in the adapter and we do not have to call findViewById()many times. So, it is for optimization.

我也从viewholder了解到,我们可以在adapter中保存子视图,不需要findViewById()多次调用。所以,这是为了优化。

But I have only the confusion in setTag(holder)and getTag()methods. From this question, I came to know that it is for making a key-value pair on multiple objects, so that we can access them easily. But, I do not understand why they are required here...because, we do not have multiple holder objects...only we have to change holder's variables each time. can we code here without using setTagand getTag?

但我只有混淆setTag(holder)getTag()方法。从这个问题,我开始知道它是为了在多个对象上制作键值对,以便我们可以轻松访问它们。但是,我不明白为什么这里需要它们……因为,我们没有多个持有者对象……只有我们每次都必须更改持有者的变量。我们可以在这里编码而不使用setTagandgetTag吗?

can anyone explain better that what setTagand getTagdo "here"?

谁能更好地解释“在这里”做什么setTaggetTag做什么?

回答by mmlooloo

tagis a mechanism to make your viewsremember something, that could be an objectan integera stringor anything you like.

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

so when your ListViewis going to create for the first time your convertViewis null. so you create a new convertViewand put all of your referencesof the objectsof that rowin a viewHolder. then save your viewHolderinto the memory of that convertView(setTag). Androidtakes your convertViewand puts it in its poolto recycleit and passesit again to you. but its poolmay not have enough convertViewsso it again passes a new convertViewthats null. so again the story is repeated till the poolof androidis filled up. after that androidtakes a convertViewfrom its pool and passes it to you. you will find that its not nullso you ask it where are my object referencesthat I gave to you for the first time? (getTag) so you will get those and do whatever you like.

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

More elaboration on below line

下一行的更多详细说明

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

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

android poolis empty when your listViewis going to create. so for the first item of your listViewit sends you a convertViewthat must be displayed. after that androidsaves it in its pool, so its poolnow contains just one convertView. for your second item of your listViewthat is going to create android can not use its pool because it is actually has one element and that element is your first item and it is being shown right now so it has to pass another convertView. this process repeates until androidfound a convertViewin its poolthats not being displayed now and passes it to you.

pool当您listView要创建时,android为空。因此,对于您的第一项,listView它会向您发送一个convertView必须显示的信息。之后android将它保存在它的pool,所以它pool现在只包含一个convertView. 对于您listView将要创建的第二个项目,android 无法使用其池,因为它实际上有一个元素,而该元素是您的第一个项目,并且它现在正在显示,因此它必须通过另一个convertView。这个过程会重复,直到在它现在没有显示的地方android找到一个并将它传递给你。convertViewpool

Android inflates each row till the screen filled up after that when you scroll the list it uses holder.

当您滚动列表时,Android 会膨胀每一行,直到屏幕填满为止。

回答by neferpitou

Lets Look in a Different Perspective:

让我们换个角度看:

enter image description here

在此处输入图片说明

Lets imagine that the Helicopteris the "row" while the ropeis the "setTag" and the carbelow is "WeatherHolder", but the pilot of the Helicopter is inside that car and he/she the one managing controlling the helicopter using a "WIRED REMOTE".

让我们想象一下直升机是“”,而绳子是“ setTag”,下面的是“ WeatherHolder”,但是直升机的飞行员在那辆车里,他/她是使用“控制直升机的人”有线遥控器”。

When you cut the Rope Which is "setTag" the Hellicopter still fly but the pilot can no longer control it since the pilot is drop in the ground which means the pilot is now dead! (In java when an object loss its reference the Garbage Collector will collect that and free from the memory).

当你切断“setTag”的绳子时,直升机仍然飞行,但飞行员无法再控制它,因为飞行员掉在地上,这意味着飞行员现在已经死了!(在 Java 中,当对象丢失其引用时,垃圾收集器将收集该对象并从内存中释放)。

When you did not place or attach the rope to the car while the Helicopter is about to fly where the Pilot is sitting - you potentially loss a control on the helicopter because you are using "WIRED REMOTE".

如果在直升机即将飞到飞行员所在的位置时您没有将绳索放置或连接到汽车上 - 您可能会失去对直升机的控制,因为您使用的是“有线遥控”。

I hope this help :).

我希望这会有所帮助:)。

回答by Andrew Breen

But, I do not understand why they are required here...because, we do not have multiple holder objects

但是,我不明白为什么这里需要它们......因为,我们没有多个持有者对象

This is where you are wrong - there is one holder per view (aka visible or cached ListView entry).

这就是你错的地方——每个视图有一个持有者(也就是可见或缓存的 ListView 条目)。