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


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

Возможное решение проблемы Аскера, но не лучшее решение. Не должен быть отмечен как ответ ...
— angryITguy

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 назначает уникальный идентификатор ресурса 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.


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"/>



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;

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.