【问题标题】:What is the main purpose of setTag() getTag() methods of View?View 的 setTag() getTag() 方法的主要目的是什么?
【发布时间】:2011-07-14 14:03:30
【问题描述】:

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

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

【问题讨论】:

    标签: android view android-view android-viewholder


    【解决方案1】:

    我想补充几句。

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

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

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

    • 它只存储了一个Object,当你想getTag时需要转换它。当您决定更改标签中存储对象的类型时,以后可能会发生意外崩溃。

    • 这是一个真实的故事:我们有一个相当大的项目,其中包含很多适配器、带有视图的异步操作等等。一位开发人员决定在他的部分代码中使用set/getTag,但另一位开发人员已经为这个视图设置了标签。最后,有人找不到自己的标签,很困惑。我们花了几个小时才找到这个错误。

    setTag(int key, Object tag) 看起来好多了,因为您可以为每个标签生成唯一的键(使用id resources),但是对于 Android

    Android 4.0之前,View.setTag(int, Object)的实现 会将对象存储在静态地图中,其中的值是 强烈引用。这意味着如果对象包含任何 指向上下文的引用,上下文(指向 几乎所有其他东西)都会泄漏。如果您传递一个视图,该视图 提供对创建它的上下文的引用。同样,查看 持有者通常包含一个视图,游标有时也 与视图相关联。

    【讨论】:

    • 谢谢,非常有帮助! ...您是否碰巧知道标签中的内容是否在活动娱乐之间恢复?
    【解决方案2】:

    假设您生成了一堆相似的视图。您可以为每个视图单独设置一个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());
        }
    };
    

    这基本上是视图拥有记忆的一种方式。

    【讨论】:

    • @Matthew Willis 但我们也可以使用 view.getId() 来做到这一点。不是吗?
    • @AndroidKiller 你可以,但是使用 setTag() 你可以放置任何你想要的对象,甚至是自定义类——这样你就可以使用它们来持久化对视图正在显示的数据的引用
    • 如果我只想更改被点击按钮的背景颜色该怎么办?我通过 getTag() 获得职位。
    • @Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); } 应该可以解决颜色部分的问题。 20 只是您的视图的验证位置的占位符。
    • 我认为这是老办法。新方法是使用提供类型安全的泛型参数。但这仍然很好。
    【解决方案3】:

    当您有一个 ListView 并想要回收/重用视图时,标签的设置非常有用。这样一来,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;
    }
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        例如,

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

        【讨论】:

          【解决方案6】:

          这对于自定义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);
              }
                      ....................
          }
          

          【讨论】:

            【解决方案7】:

            对于 web 开发者来说,这似乎相当于 data-..

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-11-15
              • 2014-10-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-11-08
              • 1970-01-01
              相关资源
              最近更新 更多