Ключ должен быть идентификатором ресурса приложения

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;
Pentium10
источник

Ответы:

55

Идентификатор тега должен быть уникальным, поэтому он должен быть идентификатором, созданным в файле ресурсов, чтобы гарантировать уникальность.

Если представление будет содержать только один тег, хотя вы можете просто сделать

setTag(objContact.onlineid);
Робби Понд
источник
3
Я до сих пор не понимаю шаблон. Я хочу установить два тега, соответствующие сказать имя и фамилию. где я могу определить целочисленные идентификаторы для них?
Джеффри Блатман
7
Вы можете использовать любой ресурс - даже просто взять случайный R.id.FOO, где FOO - это некоторый идентификатор в вашем проекте.
Артем Руссаковский
16
Это лучший способ получить уникальный идентификатор тега? Действительно Android?
jimmy0251
Привет, что если я не знаю, сколько тегов? потому что я хочу генерировать представления по некоторым данным в модели ....
jsina
Возможное решение проблемы Аскера, но не лучшее решение. Не должен быть отмечен как ответ ...
angryITguy
226

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

Попробуйте создать две уникальные записи в String.xml xml, скажем, «имя» и «имя» и используйте их, как показано ниже

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");
ABDroids
источник
129
добавьте это в свой файл strings.xml: <item type = "id" name = "TAG_ONLINE_ID" />, и вы можете использовать его как обычный ресурс id: R.id.TAG_ONLINE_ID
EtienneSky
9
этот должен быть ответом. его более общий.
IronBlossom
2
@AjithMemana почему? Когда приложение компилируется, файл strings.xml назначает уникальный идентификатор ресурса int каждому элементу. Значение строкового элемента не учитывается.
ataulm
1
Спасибо, это так здорово и полезно ... также, если вы хотите получить тег, вам нужен доступ к строковым значениям, таким как v.getTag (R.string.name)
Amt87
5
Лучше создайте имя файла ids.xml в каталоге res / values и добавьте туда все свои уникальные идентификаторы.
vovahost
146

Я немного опоздал на вечеринку, но сегодня я сам наткнулся на эту проблему и подумал, что тоже дам ответ. Этот ответ будет немного обобщением других ответов, но с изюминкой. Прежде всего, id, как было указано другими, НЕ может быть константой, определенной в вашем коде (например, private static final int MYID = 123) или любым другим int, который вы определяете как поле где-либо.

Идентификатор должен быть предварительно скомпилированным уникальным идентификатором, точно так же как те, которые вы получаете для строк, которые вы помещаете в values ​​/ 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.

britzl
источник
14
Вы даже можете сделать это, <item name="TAG_ONLINE_ID" type="id"/>чтобы упростить.
Бенуа Даффес
Это реальное решение; Не новичок «Я не понимаю, что я делаю, но этот хак работает»
Роэль
обратите внимание, чтобы получить доступ в коде использовать R.id..., а не R.string.. илиR.tags...
g2server
Это было полезно, и вот еще один пост, где он показывает его использование: stackoverflow.com/questions/28492493/…
prasad_
И убедитесь, что вы поместили файл в значения, а не в папку xml. :)
Нантока
55

ЭТО ДЕЛАЕТ РАБОТУ ...

Если у вас есть только 1 setTag в вашем классе, вы можете использовать любой int, может быть static final, объявленный в верхней части.

Проблема возникает, когда у вас есть 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.
Переполнение
Нет. Должно быть больше 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"/>

ViliusK
источник
0

Это работает для меня:

setTag(0xffffffff,objContact.onlineid);
Ю Сяофэй
источник
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;

для уникального идентификатора ресурса приложения

Джеки Ченг
источник