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

Eug*_*ene 406 android view android-view android-viewholder

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

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

Mat*_*lis 619

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

button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
 ...
Run Code Online (Sandbox Code Playgroud)

然后,您必须onClick为每个视图创建一个唯一的方法,即使它们执行类似的操作,例如:

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

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

输入getTag/ setTag:

button1.setTag(1);
button2.setTag(2);
Run Code Online (Sandbox Code Playgroud)

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

listener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        doAction(v.getTag());
    }
};
Run Code Online (Sandbox Code Playgroud)

它基本上是一种观赏记忆的方式.

  • @AndroidKiller你可以,但是使用setTag()你可以放置你想要的任何对象,甚至是自定义类 - 这样你就可以使用它们来持久引用视图所显示的数据 (49认同)
  • @Matthew Willis但我们也可以使用view.getId()来做到这一点.是不是 ? (8认同)
  • @Sagar:`public void ui_click(View view){if(20 ==((int)view.getTag()))view.setBackgroundColor(colorInt); }`应该为颜色部分做技巧.20只是占位符,用于验证View的位置. (2认同)

And*_*yeu 121

我想补充几句话.

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

主要原因是代码很快就变得不受支持了.

  • 对于其他开发人员而言,您设计为在视图中存储为标记的内容并不明显.方法setTag/getTag根本不具有描述性.

  • 它只存储一个Object,所以它需要你想要的演员表getTag.当您决定更改标记中存储对象的类型时,您可能会在以后遇到意外崩溃.

  • 这是来自现实生活的故事.我们有一个非常大的项目,包含很多适配器,带有视图的异步操作等等.一位开发人员决定使用set/getTag他的部分代码,但另一位开发人员已经为此视图设置了标记.最后有人找不到自己的标签而且非常困惑.花了我们几个小时来找到这个bug.

setTag(int key, Object tag)看起来好多了,因为你可以为每个标签生成唯一的密钥(使用id资源),但Android <4.0存在重大限制.来自Lint文档:

在Android 4.0之前,View.setTag(int,Object)的实现会将对象存储在静态映射中,其中值被强烈引用.这意味着如果对象包含指向上下文的任何引用,则上下文(指向其他所有内容)将泄漏.如果传递视图,视图将提供对创建它的上下文的引用.类似地,视图持有者通常包含视图,而游标有时也与视图相关联.

  • 谢谢,非常有帮助!...您是否碰巧知道标签中的内容是否在活动重新创建之间恢复? (2认同)

Ram*_*ash 25

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

例如,

Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Run Code Online (Sandbox Code Playgroud)


Ore*_*ren 19

对于Web开发人员来说,这似乎等同于数据 - ..


小智 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);
    }
            ....................
}
Run Code Online (Sandbox Code Playgroud)


Saa*_*lal 13

与ID不同,标签不用于标识视图.标签本质上是可以与视图相关联的额外信息.它们通常用作存储与视图本身中的视图相关的数据的便利,而不是将它们放在单独的结构中.

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


小智 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;
}
Run Code Online (Sandbox Code Playgroud)