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


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.