Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a simple code snippet for implementing custom listview.

My code is as follows:

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

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.

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.

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 setTag and getTag?

can anyone explain better that what setTag and getTag do "here"?

like image 425
xyz Avatar asked Sep 22 '14 04:09

xyz


People also ask

What is the use of setTag in Android?

Prior to Android 4.0, the implementation of View. setTag(int, Object) would store the objects in a static map, where the values were strongly referenced. This means that if the object contains any references pointing back to the context, the context (which points to pretty much everything else) will leak.

What is the ViewHolder pattern?

The ViewHolder design pattern enables you to access each list item view without the need for the look up, saving valuable processor cycles. Specifically, it avoids frequent call of findViewById() during ListView scrolling, and that will make it smooth.

What is the use of ViewHolder?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results.


2 Answers

tag is a mechanism to make your views remember something, that could be an object an integer a string or anything you like.

so when your ListView is going to create for the first time your convertView is null. so you create a new convertView and put all of your references of the objects of that row in a viewHolder. then save your viewHolder into the memory of that convertView(setTag). Android takes your convertView and puts it in its pool to recycle it and passes it again to you. but its pool may not have enough convertViews so it again passes a new convertView thats null. so again the story is repeated till the pool of android is filled up. after that android takes a convertView from its pool and passes it to you. you will find that its not null so you ask it where are my object references that I gave to you for the first time? (getTag) so you will get those and do whatever you like.

More elaboration on below line

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

android pool is empty when your listView is going to create. so for the first item of your listView it sends you a convertView that must be displayed. after that android saves it in its pool, so its pool now contains just one convertView. for your second item of your listView that 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 android found a convertView in its pool thats not being displayed now and passes it to you.

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

like image 59
mmlooloo Avatar answered Sep 24 '22 04:09

mmlooloo


Lets Look in a Different Perspective:

enter image description here

Lets imagine that the Helicopter is the "row" while the rope is the "setTag" and the car below 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".

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

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 :).

like image 41
neferpitou Avatar answered Sep 23 '22 04:09

neferpitou