View的setTag() getTag()方法的主要目的是什么?

View类型对象的setTag()getTag()等方法的主要目的是什么?

我认为我可以将任意数量的对象与单个视图相关联是正确的吗?

277693 次浏览

假设你生成了一堆相似的视图。你可以为每个视图单独设置OnClickListener:

button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...

然后你必须为每个视图创建一个唯一的onClick方法,即使它们做类似的事情,比如:

public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}

这是因为onClick只有一个参数View,它必须从封闭作用域的实例变量或最终局部变量中获取其他信息。我们真正想要的是获取信息从视图本身

进入getTag / setTag:

button1.setTag(1);
button2.setTag(2);

现在我们可以对每个按钮使用相同的OnClickListener:

listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};

它基本上是视图具有记忆的一种方式。

这对于自定义使用ArrayAdapter非常有用。这是一种优化。其中,setTag被用作引用对象,该对象引用布局的某些部分(显示在ListView中),而不是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);
}
....................
}

我想补充几句话。

虽然在ViewHolder模式的特定情况下使用get/setTag(Object)似乎非常有用,但我建议在其他情况下使用它之前要三思。几乎总有其他设计更好的解决方案。

主要原因是这样的代码很快就会变得不受支持。

  • 对于其他开发人员来说,您在视图中作为标签存储的内容是不明显的。方法setTag/getTag根本不是描述性的。

  • 它只是存储了一个Object,当你想要getTag时需要强制转换。稍后当您决定更改标记中存储的对象类型时,可能会出现意外的崩溃。

  • 这里有一个真实的故事:我们有一个相当大的项目,有很多适配器,视图异步操作等等。一个开发人员决定在他的部分代码中set/getTag,但另一个开发人员已经将标记设置为这个视图。最后,有人找不到自己的标签,非常困惑。我们花了好几个小时才找到漏洞。

setTag(int key, Object tag)看起来更好,因为你可以为每个标签生成唯一的键(使用id资源),但对于Android <4.0. 来自Lint docs:

在Android 4.0之前,视图的实现。setTag (int对象) 将对象存储在静态映射中,值在哪里 强引用。这意味着如果对象包含任何 引用指向上下文,上下文(它指向 几乎所有其他东西)都会泄漏。如果你传递一个视图,视图 提供对创建它的上下文的引用。同样,视图 holder通常包含一个视图,游标有时也包含

.关联视图

对于web开发人员来说,这似乎相当于数据-..

与id不同,标记不用于标识视图。标签本质上是可以与视图相关联的额外信息。它们最常用来方便地在视图本身中存储与视图相关的数据,而不是将它们放在一个单独的结构中。

参考:http://developer.android.com/reference/android/view/View.html

我们可以根据需要使用setTag()getTag()来设置和获取自定义对象。setTag()方法接受一个类型为Object的参数,并且getTag()返回一个Object

例如,

Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);

当你有一个ListView并且想要回收/重用视图时,TAGs的设置非常有用。这样,ListView变得非常类似于更新的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;
}