Ключ повинен бути ідентифікатором ресурсу, що залежить від програми


145

Чому я отримую цей виняток?

05-18 20:29:38.044: ERROR/AndroidRuntime(5453): java.lang.IllegalArgumentException: The key must be an application-specific resource id.
05-18 20:29:38.044: ERROR/AndroidRuntime(5453):     at android.view.View.setTag(View.java:7704)
05-18 20:29:38.044: ERROR/AndroidRuntime(5453):     at com.mypkg.viewP.inflateRow(viewP.java:518)

мова про яку йдеться:

((Button) row.findViewById(R.id.btnPickContact)).setTag(TAG_ONLINE_ID,objContact.onlineid);

і у мене це визначено як:

private static final int TAG_ONLINE_ID = 1;

Відповіді:


55

Ідентифікатор тегу повинен бути унікальним, тому він хоче бути ідентифікатором, створеним у файлі ресурсів, щоб гарантувати унікальність.

Якщо представлення буде містити лише один тег, ви можете просто зробити

setTag(objContact.onlineid);

3
я досі не отримую схему. я хочу встановити два теги, відповідні сказати ім’я та прізвище. де я визначаю цілі ідентифікатори для них?
— Джефрі Блатман

7
Ви можете використовувати будь-який ресурс - навіть просто взяти випадковий R.id.FOO, де FOO - якийсь ідентифікатор у вашому проекті.
— Артем Русаковський

16
Це найкращий спосіб отримати унікальний ідентифікатор тегу? Дійсно Android?
— jimmy0251

Гей, а що, якщо я не знаю, скільки тегів? тому що я хочу генерувати перегляди за деякими даними в моделі ....
— jsina

Можливе рішення проблеми Аскера, але це не найкраще рішення. Не слід позначати як відповідь ...
— сердитоTguy

226

Причина, по якій ви не можете використовувати setTag (int, Object), полягає в тому, що для android потрібен попередньо скомпільований унікальний ідентифікатор в аргументі 'int'.

Спробуйте створити два унікальних записи у String.xml xml, скажімо, "ім'я" та "друге ім'я", і використовуйте їх як нижче

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");

129
додайте це у файл strings.xml: <item type = "id" name = "TAG_ONLINE_ID" />, і ви можете використовувати як звичайний ресурс id: R.id.TAG_ONLINE_ID
— EtienneSky

9
на це має бути відповідь. його більш загальне.
— IronBlossom

2
@AjithMemana чому? Коли програма складається, файл strings.xml присвоює кожному елементу унікальний ідентифікатор ресурсу. Значення елемента рядка не враховується.
— ataulm

1
Дякую, що так чудово і корисно ... також якщо ви хочете отримати тег, вам потрібно отримати доступ до значень рядків, таких як v.getTag (R.string.name)
— Amt87

5
Краще створіть ім’я файлу ids.xml в каталозі res / values і додайте туди всі свої унікальні ідентифікатори.
— vovahost

146

Я трохи запізнююся на вечірку, але сьогодні я натрапив на цю проблему і подумав, що також дам відповідь. Ця відповідь буде трохи компіляцією інших відповідей, але з поворотом. Перш за все, ідентифікатор, як вказували інші, НЕ може бути константою, визначеною у вашому коді (наприклад, приватний статичний остаточний int MYID = 123) або будь-який інший int, який ви десь визначаєте як поле.

Ідентифікатор повинен бути попередньо складеним унікальним ідентифікатором, як і ті, які ви отримуєте для рядків, які ви вводите у значення / strings.xml (тобто R.string.mystring). Зверніться до http://developer.android.com/guide/topics/resources/available-resources.html та http://developer.android.com/guide/topics/resources/more-resources.html для отримання додаткової інформації.

Я пропоную вам створити новий файл під назвою values ​​/ tags.xml і написати:

    <resources xmlns:android="http://schemas.android.com/apk/res/android">
      <item name="TAG_ONLINE_ID" type="id"/>
    </resources>

Я думаю, що краще створити окремий файл, а не ставити його у strings.xml, як запропонував EtienneSky.


14
Ви навіть можете зробити це <item name="TAG_ONLINE_ID" type="id"/>для спрощення.
— Бенуа Даффез

Це справжнє рішення; Не новачок "Я не розумію, що я роблю, але цей хак працює"
— Roel

зауважте, щоб отримати доступ до використання коду R.id..., а не R.string.. абоR.tags...
— g2server

Це було корисно , і ось ще один пост , де він показує його використання: stackoverflow.com/questions/28492493 / ...
— prasad_

І переконайтеся, що ви помістили файл у значення, а не у папку xml. :)
— Nantoka

55

ЦЕ БУДЕ РОБОТУ ...

Якщо у вас просто 1 setTag у вашому класі, ви можете використовувати будь-який int, можливо, статичний фінал, оголошений вгорі.

Проблема виникає, коли у вас було 2 або більше setTag з різними клавішами. Я маю на увазі:

public static final int KEY_1 = 1;
public static final int KEY_2 = 2;
...
setTag(KEY_1)
setTag(KEY_2)
...

Цей сценарій неправильний. Потім потрібно додати файл значення, який називається, можливо, ids.xml із наступним:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item type="id" name="resourceDrawable" />
    <item type="id" name="imageURI" />
</resources>

Потім у своєму класі зателефонуйте:

 ...
 setTag(R.id.resourceDrawable, KEY_1)
 setTag(R.id.imageURI, KEY_2)
 ...

найкраще пояснення для новачків
— Річард Ле Месюр'є

Це справжнє рішення: не виправити хакі для новачків!
— Roel

8
private static final int TAG_ONLINE_ID = 1 + 2 << 24;

повинен працювати. Більше інформації від ceph3us :

Зазначений ключ повинен бути ідентифікатором, оголошеним у ресурсах програми, щоб переконатися, що унікальні ключі, ідентифіковані як рамки Android або не пов'язані з будь-яким пакетом, призведуть до закидання IllegalArgumentException.

з джерела:

public void setTag(int key, final Object tag) {
    // If the package id is 0x00 or 0x01, it's either an undefined package
    // or a framework id
    if ((key >>> 24) < 2) {
        throw new IllegalArgumentException("The key must be an application-specific "
                + "resource id.");
    }

    setKeyedTag(key, tag);
}

Тому що ідентифікатор повинен бути створений у вашому файлі R.java
— StackOverflowed

Ні, це не є. Вона повинна бути більше 2 << 24, ось і все.
— Антон Дузенко

Добре, що підхід 1 + 2 << 24, 2 + 2 << 24 і т.д. справді працює. Виглядає як неправильне виправлення. Мені подобається знати, чому це так? Чи є якісь ризики, наприклад, у майбутніх версіях Android тощо? Набагато складніше використовувати його, визначене як константу?
— Ян Бергстрьом

Тому що він твердо кодується в Android SDK. Це ніколи не зміниться, оскільки в іншому випадку всі існуючі програми для Android перестануть працювати.
— Антон Дузенко

1
Я думаю, що головна проблема цього рішення полягає в тому, що він не гарантує унікальність цього ключа, а це означає, що додавши якусь бібліотеку чи інший код, який використовує функцію setTag, ця логіка може порушитися, якщо згенерований ідентифікатор буде відповідати одному, отриманому з цього рішення.
— EdgarK

3

Я звик viewHolder.itemTitleTextView.getId(). Але ви також можете заявити у своїх ресурсах: <item type="id" name="conversation_thread_id"/>



0

Причина, чому ви хочете зберегти значення за допомогою ідентифікатора, полягає в тому, що ви хочете охопити більше одного значення в цьому тезі, правда?
Ось більш просте рішення:
Скажімо, ви хочете зберегти два значення (рядки) у цей тег: "ім'я" та "прізвище". Ви можете зберегти їх обома в один рядок, розділений крапкою з комою:

v.setTag(firstname + ";" + lastname);

... і отримати доступ до них, розділивши їх на масив рядків:

String[] data = v.getTag().toString().split(";");
System.out.println(data[0]) //firstname
System.out.println(data[1]) //lastname

0

Ви можете скористатися цим:

private static final int TAG_ONLINE_ID = View.generateViewId() + 2 << 24;

для ідентифікатора ресурсу, що відповідає додатку uniqness

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.