Яка основна мета методів перегляду setTag () getTag ()?


421

Яка головна мета таких методів , як setTag()і getTag()з Viewоб'єктів типу?

Я маю рацію, думаючи, що я можу пов’язати будь-яку кількість об'єктів з одним Видом?

Відповіді:


636

Скажімо, ви формуєте купу схожих поглядів. Ви можете встановити 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є лише один параметр a View, і він повинен отримувати іншу інформацію зі змінних екземплярів або кінцевих локальних змінних, що додаються в область застосування. Ми дійсно хочемо отримати інформацію з самих поглядів .

Введіть getTag/ setTag:

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

Тепер ми можемо використовувати той самий OnClickListener для кожної кнопки:

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

Це, в основному, спосіб перегляду мати спогади .


8
@Matthew Willis, але ми можемо це зробити і за допомогою view.getId (). це не воно ?
Android Killer

50
@AndroidKiller ви могли б, але за допомогою setTag () ви можете розмістити будь-який потрібний вам об’єкт, навіть користувацькі класи - так що ви можете використовувати їх для збереження посилання на дані, які відображає погляд
Деніел

Що мені робити, якщо я хочу змінити колір тла кнопки, що натискається ??? Я отримую позицію через getTag ().
Сагар Деванга

2
@Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }повинен зробити трюк для кольорової частини. 20 - це лише заповнювач місця для валідаційної позиції вашого представлення даних.
RiA

Я думаю, це старий шлях. новий спосіб полягає у використанні загальних аргументів, які забезпечують безпеку типу. але це все-таки добре.
М.казем Ахгарі

124

Я хотів би додати кілька слів.

Хоча використання get/setTag(Object)здається дуже корисним у конкретному випадку шаблону ViewHolder, я рекомендую подумати двічі, перш ніж використовувати його в інших випадках. Майже завжди є ще одне рішення з кращим дизайном.

Основна причина полягає в тому, що подібний код стає швидко непідтримуваним.

  • Для інших розробників не очевидно, що ви планували зберігати як тег у представленні. Методи setTag/getTagвзагалі не є описовими.

  • Він просто зберігає таку Object, яку потрібно передати, коли захочете getTag. Пізніше ви можете отримати несподівані збої, коли вирішите змінити тип збереженого об’єкта в тезі.

  • Ось історія з реального життя: у нас був досить великий проект з великою кількістю адаптерів, операцій з асинхронізацією з видами тощо. Один розробник вирішив ввести set/getTagсвою частину коду, але інший вже встановив тег на цей вид. Зрештою, хтось не зміг знайти власний тег і дуже розгубився. Щоб знайти помилку нам коштувало кілька годин.

setTag(int key, Object tag)виглядає набагато краще, тому що ви можете генерувати унікальні ключі для кожного тегу (використовуючи ресурси id ), але для 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);

20

Для веб-розробників це здається еквівалентом даних ...


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);
    }
            ....................
}

13

На відміну від ідентифікаторів, теги не використовуються для ідентифікації представлень. Теги - це, по суті, додаткова інформація, яка може бути пов’язана з переглядом. Вони найчастіше використовуються як зручність для зберігання даних, пов’язаних із переглядами, у самих поданнях, а не шляхом їх розміщення в окремій структурі.

Довідка: http://developer.android.com/reference/android/view/View.html


11

Налаштування TAG дуже корисно, коли у вас є 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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.