密钥必须是特定于应用程序的资源ID


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;

Answers:


55

标签ID必须是唯一的,因此它希望它是在资源文件中创建的ID以确保唯一性。

如果视图仅包含一个标签,尽管您可以

setTag(objContact.onlineid);

3
我仍然不明白这种模式。我想设置两个标签以分别说出名字和姓氏。我在哪里为这些定义整数ID?
杰弗里·布拉特曼

7
您可以使用任何资源-甚至可以随机获取R.id.FOO,其中FOO是项目中的某些ID。
Artem Russakovskii 2011年

16
这是获得唯一标签ID的最佳方法?真的是Android吗?
jimmy0251 2015年

嘿,如果我不知道有几个标签怎么办?因为我想根据模型的一些数据来生成视图....
jsina

解决问号者问题的可能解决方案,但不是最佳解决方案。不应该将其标记为答案...
AngryITguy '16

226

您无法使用setTag(int,Object)的原因是因为android在'int'参数中要求预编译的唯一ID。

尝试在String.xml xml中创建两个唯一条目,例如“ firstname”和“ secondname”,并按如下所示使用它们

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 2011年

9
这应该是答案。它更通用。
IronBlossom

2
@AjithMemana为什么?编译应用程序时,strings.xml文件为每个元素分配一个唯一的int资源ID。不考虑string元素的值。
ataulm 2013年

1
谢谢您,它非常有用而且很有帮助...同样,如果您想获取标签,则需要访问字符串值,例如v.getTag(R.string.name)
Amt87,2014年

5
最好在res / values目录中创建一个文件名ids.xml,然后在其中添加所有唯一ID。
vovahost

146

我参加聚会有点晚了,但今天我自己偶然发现了这个问题,并认为我也会给出答案。该答案将是其他答案的一部分,但有所不同。首先,正如其他人指出的那样,id不能是代码中定义的常量(例如private static final int MYID = 123)或您定义为某个字段的任何其他int。

该ID必须是预编译的唯一ID,就像您在values / strings.xml(即R.string.mystring)中输入的字符串所获得的ID一样。有关更多信息,请参见http://developer.android.com/guide/topics/resources/available-resources.htmlhttp://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>

我认为最好创建一个单独的文件,而不是像EtienneSky建议的那样将其放在strings.xml中。


14
您甚至可以<item name="TAG_ONLINE_ID" type="id"/>简化它。
Benoit Duffez

这是真正的解决方案。不是新手,“我不明白我在做什么,但是这种黑客有效”的解决方案
Roel

注,在代码中使用的进入R.id...,并没有 R.string..或者R.tags...
g2server

这很有用,这是另一篇文章,其中显示了它的用法:stackoverflow.com/questions/28492493/…–
prasad_

并确保将文件放在值中,而不是xml文件夹中。:)
Nantoka

55

这将使工作...

如果您的类中只有1个setTag,则可以使用任何int,也可以使用在顶部声明的static final。

当您有两个或多个带有不同键的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)
 ...

对新移民的最佳解释
Richard Le Mesurier

这是真正的解决方案:不是新手破解!
Roel

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

应该管用。来自ceph3us的更多信息:

指定的密钥应该是在应用程序资源中声明的ID,以确保其唯一标识为属于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);
}

因为ID必须是R.java文件中生成的ID。
StackOverflow 2013年

不,不是的。它必须大于2 << 24,仅此而已。
安东·杜赞科

好吧,1 + 2 << 24,2 + 2 << 24等方法实际上有效。看起来像是不规则的修复。我想知道为什么会这样吗?是否存在任何风险,例如在未来的Android等版本中?到目前为止,使用它定义为常量是令人窒息的吗?
JanBergström'16

因为它在Android SDK中是硬编码的。它永远不会改变,因为否则所有现有的android应用将停止工作。
安东·杜赞科

1
我猜想此解决方案的主要问题在于它不能保证此键的唯一性,这意味着,如果生成的ID与该解决方案中的一个匹配,则通过添加一些使用setTag功能的库或其他代码,此逻辑可能会中断。
EdgarK

3

我已经习惯了viewHolder.itemTitleTextView.getId()。但是您也可以在资源中声明: <item type="id" name="conversation_thread_id"/>



0

您想通过ID保存值的原因是,您想在此标记中覆盖多个值,对吗?
这里是一个更简单的解决方案:
假设您要将两个值(字符串)保存到此标记中:“名字”和“姓氏”。您可以将它们保存在一个字符串中,用分号分隔:

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;

用于特定于应用程序的唯一资源ID

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.