Android: назначение getTag () и setTag () в классе просмотра

public void setTag(final Object tag) {
                mTag = tag;
}
public Object getTag() {
            return mTag;
}

Это два метода из класса View в Android. Ниже приводится официальная документация по этим двум методам соответственно.

 /**
     * Returns this view's tag.
     *
     * @return the Object stored in this view as a tag
     *
     * @see #setTag(Object)
     * @see #getTag(int)


        */
 /**
     * Sets the tag associated with this view. A tag can be used to mark
     * a view in its hierarchy and does not have to be unique within the
     * hierarchy. Tags can also be used to store data within a view without
     * resorting to another data structure.
     *
     * @param tag an Object to tag the view with
     *
     * @see #getTag()
     * @see #setTag(int, Object)
     */

функции тегов широко используются в реализации baseadapter, но я не мог понять его цель и как их использовать. Не могли бы вы объяснить этот хороший пример, чтобы помочь мне понять роль этих функций

5 ответов


подумайте об этом так просто, как это возможно - "тег".

что бирка продукта продуктового магазина говорит вам? В основном много вещей, таких как имя, цена, страна происхождения, скидка и многие другие.

представьте, что вы создаете приложение, которое отображает такие продукты в сетке с помощью ImageView. Как легко определить характеристики продукта от книги? Маркировка-одно из возможных решений.

class Product {

    String mName;
    String mManufacturer;
    String mOriginCountry;

    double mPrice;
    int mDiscount;

    int mImageId; // A reference to a drawable item id
}

[...]

class My Activity {

    @Override
    protected void onCreate() {
        [...] // Some code

        // Grab the imageView reference and grab (or create) the tag for it
        ImageView someItemView = (ImageView) findViewById(R.id.some_product_view);
        Product someProductTag = new Product( ... some data ...);

        // Add the tag to the ImageView
        someItemView.addTag(someProductTag);
    }

    private void displayItemInfo(ImageView iv) {

        // Grab the tag and display the info.
        String productName = ((Product)iv.getTag()).mName();
        Toast.show(mContext, "This is " + productName, Toast.LONG).show(); 

    }

}

конечно, это очень упрощенный. В идеале у вас будет адаптер, который создаст представление на основе предоставленных вами тегов или создаст ваши теги автоматически.

надеюсь, вы поняли идею


хорошим примером является шаблон держателя вида. Реализация может быть найдена в в этом уроке на ListViews.

шаблон держателя вида позволяет избежать метода findViewById () в адаптере.

класс ViewHolder-это статический внутренний класс в вашем адаптере, который содержит ссылки на соответствующие представления. в макете. Эта ссылка назначается представлению строки в виде тега с помощью метода setTag ().

Если мы получим объект convertView, мы можем получить экземпляр ViewHolder с помощью метода getTag () и назначить новые атрибуты представлениям с помощью ссылки ViewHolder.

хотя это звучит сложно, это примерно на 15 % быстрее, чем использование метода findViewById ().

пример

следующий код показывает оптимизированную для производительности реализацию адаптера, которая повторно использует существующие представления и реализует держатель узор.

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyPerformanceArrayAdapter extends ArrayAdapter<String> {
  private final Activity context;
  private final String[] names;

  static class ViewHolder {
    public TextView text;
    public ImageView image;
  }

  public MyPerformanceArrayAdapter(Activity context, String[] names) {
    super(context, R.layout.rowlayout, names);
    this.context = context;
    this.names = names;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    // reuse views
    if (rowView == null) {
      LayoutInflater inflater = context.getLayoutInflater();
      rowView = inflater.inflate(R.layout.rowlayout, null);
      // configure view holder
      ViewHolder viewHolder = new ViewHolder();
      viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
      viewHolder.image = (ImageView) rowView
          .findViewById(R.id.ImageView01);
      rowView.setTag(viewHolder);
    }

    // fill data
    ViewHolder holder = (ViewHolder) rowView.getTag();
    String s = names[position];
    holder.text.setText(s);
    if (s.startsWith("Windows7") || s.startsWith("iPhone")
        || s.startsWith("Solaris")) {
      holder.image.setImageResource(R.drawable.no);
    } else {
      holder.image.setImageResource(R.drawable.ok);
    }

    return rowView;
  }
} 

Они просто способ прикрепить Object для просмотра.
В BaseAdapter он используется для хранения идентификаторов представлений, чтобы избежать дорогостоящего findViewById операция каждый раз, когда система запрашивает представление.


setTag(int, object) очень полезно для хранения пользовательского класса в представлении. Вот моя реализация :

 itemView.setTag(R.id.food_tag, food);

переменная food является экземпляром пользовательского объекта Food. Ключом для setTag всегда должен быть идентификатор ресурса.

Я мог бы получить этот пользовательский объект таким образом в OnClickListener():

Food selectedFood = (Food) view.getTag(R.id.food_tag);

поле тега-хороший способ сохранить информацию о состоянии для любого класса представления. Одно из применений-сохранить позицию представления в ListView. Смотрите это ответ для примера.