What is the main purpose of setTag() getTag() methods of View?
Let's say you generate a bunch of views that are similar. You could set an OnClickListener
for each view individually:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
Then you have to create a unique onClick
method for each view even if they do the similar things, like:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
This is because onClick
has only one parameter, a View
, and it has to get other information from instance variables or final local variables in enclosing scopes. What we really want is to get information from the views themselves.
Enter getTag
/setTag
:
button1.setTag(1);
button2.setTag(2);
Now we can use the same OnClickListener for every button:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
It's basically a way for views to have memories.
Android:Purpose of getTag() and setTag() in View Class
Think of it as as plainly simple as it's possible - a "tag".
What does a grocery shop product tag tell you?
Basically a lot of things, such as name, price, origin country, discount, and many others.
Imagine you're making an application that displays such products in a grid using ImageView's.
How to easily determine the product features from the ImageView? Tagging it is one of the possible solutions.
class Product {
String mName;
String mManufacturer;
String mOriginCountry;
double mPrice;
int mDiscount;
int mImageId; // A reference to a drawable item id
}
[...]
class My Activity {
@Override
protected void onCreate() {
[...] // Some code
// Grab the imageView reference and grab (or create) the tag for it
ImageView someItemView = (ImageView) findViewById(R.id.some_product_view);
Product someProductTag = new Product( ... some data ...);
// Add the tag to the ImageView
someItemView.addTag(someProductTag);
}
private void displayItemInfo(ImageView iv) {
// Grab the tag and display the info.
String productName = ((Product)iv.getTag()).mName();
Toast.show(mContext, "This is " + productName, Toast.LONG).show();
}
}
Of course this is very simplified. Ideally you would have an adapter which would create the view basing on your provided tags, or would create your tags automatically.
I hope you get the idea
What is the working of setTag and getTag in ViewHolder pattern?
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.
What is the use of the View's setTag method?
Basically you can store any kind of object as tag (and cast it back when calling getTag
). This can be a simple ID or some complex data. It's some information which you associate with this view.
In the case of lists and the view holder pattern it's a simple object which contains references to views of the tagged view (group). So you don't have to call findViewById
every time when you're updating the content of the view. It's just an performance optimization.
Can we store data of list item in the view tag?
No. Because of view recycling you have (e.g.) 10 views which are reused for 1000 list items. Storing data in the tag makes no sense here. It's better to use an custom data object to store the list item state (probably the same array which contains the displayed data) or you persist it right away on list item change.
See also setTag documentation.
Android: How to use View's setTag, getTag and findViewWithTag methods?
This line is part of your culprit:
com.jacksmartie.PhotoMem.MainActivity$1.onItemClick(MainActivity.java:79)
Put a breakpoint here:
Log.d("View 1", imageView.toString());
And look what your imageview
reference object [imageView] is, I'm expecting that it is null because you aren't linking it properly.
If it is null, this means that your link to the reference view is not right. If that's the case, then you need to assign it properly like so:
Button b = findViewById(R.id.Button01);
However; since you're using what seems to be a ListView
, the pulling of that is slightly different. This means that the way you're pulling the view is wrong, do some research, should find something to help clear that up!
How to use setTag and getTag with custom adapter
your code is little bit confusing, so I give you a sample
Sample Tag class
public class MyTag
{
String code;
String image;
String web_ref;
public MyTag()
{
code=null;
image=null;
web_ref=null;
}
public MyTag(String cod,String img,String wref)
{
code=cod;
image=img;
web_ref=wref;
}
}
you want to get this values when clicked on button right ? So put this tag class object as tag on button in getView of your custom adapter
MyTag myTag=new MyTag("code","image","web_ref");
holder.button.setTag(myTag);
since you get the view clicked as argument to the your function
public void shareOnClickHandler(View v)
{
myTag=(MyTag)v.getTag();
text=myTag.code;
image2.loadUrl("http://"+myTag.image);//..... I'm not sure, thank you
webview.loadUrl(mytag.web_ref);
}
I think you get the idea, try to implement your code with this idea
Why use getTag/setTag when we can do the same with static variable
But here in my code if I replace this via simple static ViewHolder, it works fine
No, it does not.
First, you are leaking memory like a sieve.
Second, as soon as the user scrolls, your approach will break, as you will start updating the wrong ImageView
. Your code is relying upon the fact that rows never get recycled, which will only be true if either your ListView
/GridView
does not require much scrolling, or if you have a seriously messed-up adapter that is trying to avoid view recycling altogether.
Related Topics
How to Connect to Android With Adb Over Tcp
How to Get Extra Data from Intent on Android
How to Have Multiple Styles Inside a Textview
How to Format Date and Time in Android
Android Accelerometer Accuracy (Inertial Navigation)
J2Me/Android/Blackberry - Driving Directions, Route Between Two Locations
Android Min Sdk Version Vs. Target Sdk Version
How to Use Prepared Statements in Sqlite in Android
Getapplication() Vs. Getapplicationcontext()
How to Make an Imageview With Rounded Corners
Android Kotlin: Getting a Filenotfoundexception With Filename Chosen from File Picker
Make a Link in the Android Browser Start Up My App
How to Connect to My Http://Localhost Web Server from Android Emulator
Android Check Internet Connection
How to Resize a Bitmap in Android
Understanding Fragment'S Setretaininstance(Boolean)
The Apk Must Be Signed With the Same Certificates as the Previous Version