setTag()
类型对象的getTag()
和View
等方法的主要用途是什么?
我是否认为我可以将任意数量的对象与一个视图相关联?
答案 0 :(得分:607)
假设你生成了一堆相似的视图。您可以为每个视图单独设置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());
}
};
这基本上是视图有记忆的方式。
答案 1 :(得分:117)
我想补充几句话。
虽然在ViewHolder模式的特定情况下使用get/setTag(Object)
似乎非常有用,但我建议在其他情况下使用它之前要三思而后行。几乎总是有另一个好的设计解决方案。
主要原因是代码很快就变得不受支持了。
对于其他开发人员而言,您设计为在视图中存储为标记的内容并不明显。方法setTag / getTag根本不具有描述性。
它只存储Object
,因此当您想getTag
时需要强制转换。当您决定更改标记中存储对象的类型时,您可能会在以后遇到意外崩溃。
这是现实生活中的故事。我们有一个非常大的项目,包含很多适配器,带有视图的异步操作等等。一位开发人员在他的部分代码中决定set/getTag
,但另一位开发人员已经为此视图设置了标记。最后有人找不到自己的标签而且非常困惑。花了我们几个小时来找到这个错误。
setTag(int key, Object tag)
看起来好多了,因为你可以为每个标签生成唯一的密钥(使用id resources),但是对于Android< 4.0。来自Lint文档:
在Android 4.0之前,执行View.setTag(int,Object) 将对象存储在静态地图中,其中值为 强烈引用。这意味着如果对象包含任何对象 指向上下文的引用,上下文(指向 几乎所有其他东西)都会泄漏。如果您传递视图,则视图 提供对创建它的上下文的引用。同样,观点 持有者通常包含视图,有时也包含游标 与观点相关联。
答案 2 :(得分:25)
我们可以使用setTag()
和getTag()
根据我们的要求设置和获取自定义对象。 setTag()
方法采用Object
类型的参数,getTag()
返回Object
。
例如,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
答案 3 :(得分:19)
对于Web开发人员来说,这似乎等同于数据 - ..
答案 4 :(得分:14)
这对自定义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);
}
....................
}
答案 5 :(得分:11)
与ID不同,标签不用于标识视图。标签本质上是可以与视图相关联的额外信息。它们通常用作方便在视图中存储与视图相关的数据,而不是将它们放在单独的结构中。
参考:http://developer.android.com/reference/android/view/View.html
答案 6 :(得分:10)
当您拥有ListView并希望回收/重用视图时,设置TAG非常有用。通过这种方式,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;
}