问题
What is the main purpose of such methods as setTag() and getTag() of View type objects?
Am I right in thinking that I can associate any number of objects with a single View?
回答1:
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.
回答2:
I'd like to add few words.
Although using get/setTag(Object) seems to be very useful in particular case of ViewHolder pattern, I'd recommend to think twice before using it in other cases. Almost always there is another good design solution.
The main reason is that code becomes unsupportable pretty quickly.
It is non obvious for other developers what you designed to store as tag in view. Methods setTag/getTag are not descriptive at all.
It stores just an
Object, so it requires cast when you want togetTag. You can get unexpected crash later when you decide to change type of stored object in tag.This is the story from real life. We had a pretty big project with a lot of adapters, async operations with views and so on. One developer decided to
set/getTagin his part of code, but another one had already set tag to this view. In the end someone couldn't find his own tag and was very confused. That costed us several hours to find the bug.
setTag(int key, Object tag) looks much better, cause you can generate unique keys for every tag (using id resources), but there is a significant restriction for Android < 4.0. From Lint docs:
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. If you pass a view, the view provides a reference to the context that created it. Similarly, view holders typically contain a view, and cursors are sometimes also associated with views.
回答3:
We can use setTag() and getTag() to set and get custom objects as per our requirement. The setTag() method takes an argument of type Object, and getTag() returns an Object.
For example,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
回答4:
For web developers, this seems to be the equivalent to data-..
回答5:
This is very useful for custom ArrayAdapter using. It is some kind of optimization. There setTag used as reference to object that references on some parts of layout (that displaying in ListView) instead of findViewById.
static class ViewHolder {
TextView tvPost;
TextView tvDate;
ImageView thumb;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.postitem, null);
ViewHolder vh = new ViewHolder();
vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
convertView.setTag(vh);
}
....................
}
回答6:
Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.
Reference: http://developer.android.com/reference/android/view/View.html
回答7:
Setting of TAGs is really useful when you have a ListView and want to recycle/reuse the views. In that way the ListView is becoming very similar to the newer RecyclerView.
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}
来源:https://stackoverflow.com/questions/5291726/what-is-the-main-purpose-of-settag-gettag-methods-of-view