La clé doit être un identifiant de ressource spécifique à l'application

145

Pourquoi ai-je cette exception?

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)

la ligne en question est:

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

et je l'ai défini comme:

private static final int TAG_ONLINE_ID = 1;
Pentium10
la source

Réponses:

55

L'identifiant de la balise doit être unique, il veut donc qu'il s'agisse d'un identifiant créé dans un fichier de ressources pour garantir l'unicité.

Si la vue ne contient qu'une seule balise, vous pouvez simplement le faire

setTag(objContact.onlineid);
Robby Pond
la source
3
je ne comprends toujours pas le modèle. Je veux définir deux balises correspondant à dire un prénom et un nom. où puis-je définir les ID entiers pour ceux-ci?
Jeffrey Blattman
7
Vous pouvez utiliser n'importe quelle ressource - même simplement prendre un R.id.FOO aléatoire où FOO est un identifiant dans votre projet.
Artem Russakovskii
16
C'est la meilleure façon d'obtenir un identifiant de balise unique? Vraiment Android?
jimmy0251
Salut, et si je ne sais pas combien il y a de balises? parce que je veux générer des vues en fonction de certaines données du modèle ....
jsina
Une solution possible au problème du demandeur, mais ce n'est pas la meilleure solution. Ne devrait pas être marqué comme la réponse ...
angryITguy
226

La raison pour laquelle vous ne pouvez pas utiliser setTag (int, Object) est que Android nécessite un identifiant unique pré-compilé dans l'argument 'int'.

Essayez de créer deux entrées uniques dans String.xml xml, dites "firstname" et "secondname" et utilisez-les comme ci-dessous

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");
ABDroïdes
la source
129
ajoutez ceci à votre fichier strings.xml: <item type = "id" name = "TAG_ONLINE_ID" /> et vous pouvez utiliser comme une ressource d'identifiant ordinaire: R.id.TAG_ONLINE_ID
EtienneSky
9
celui-ci devrait être la réponse. c'est plus générique.
IronBlossom
2
@AjithMemana pourquoi? Lorsque l'application est compilée, le fichier strings.xml attribue un identifiant de ressource int unique à chaque élément. La valeur de l'élément string n'est pas prise en compte.
ataulm
1
Merci, c'est tellement génial et utile ... aussi si vous voulez obtenir la balise dont vous avez besoin pour accéder aux valeurs de chaînes comme v.getTag (R.string.name)
Amt87
5
Mieux vaut créer un nom de fichier ids.xml dans le répertoire res / values et y ajouter tous vos identifiants uniques.
vovahost
146

Je suis un peu en retard à la fête mais je suis tombé sur ce problème moi-même aujourd'hui et j'ai pensé que je donnerais aussi une réponse. Cette réponse sera un peu une compilation des autres réponses, mais avec une torsion. Tout d'abord, l'id, comme cela a été souligné par d'autres, ne peut PAS être une constante définie dans votre code (comme private static final int MYID = 123) ou tout autre int que vous définissez comme un champ quelque part.

L'identifiant doit être un identifiant unique précompilé, tout comme ceux que vous obtenez pour les chaînes que vous mettez dans values ​​/ strings.xml (c'est-à-dire R.string.mystring). Référez-vous aux sites http://developer.android.com/guide/topics/resources/available-resources.html et http://developer.android.com/guide/topics/resources/more-resources.html pour plus d'informations.

Ma suggestion est de créer un nouveau fichier appelé values ​​/ tags.xml et d'écrire:

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

Je pense qu'il vaut mieux créer un fichier séparé au lieu de le mettre dans strings.xml comme le suggérait EtienneSky.

britzl
la source
14
Vous pouvez même vous <item name="TAG_ONLINE_ID" type="id"/>simplifier la tâche.
Benoit Duffez
C'est la vraie solution; Pas le débutant "Je ne comprends pas ce que je fais mais ce hack fonctionne" -solution
Roel
note, pour accéder en utilisant le code R.id..., et non R.string.. ouR.tags...
g2server
Cela a été utile et voici un autre article où il montre son utilisation: stackoverflow.com/questions/28492493/…
prasad_
Et assurez-vous de mettre le fichier dans les valeurs et non dans le dossier xml. :)
Nantoka
55

CECI FERA LE TRAVAIL ...

Si vous n'avez qu'un seul setTag dans votre classe, vous pouvez utiliser n'importe quel int, peut-être statique final déclaré en haut.

Le problème survient lorsque vous avez 2 setTag ou plus avec des clés différentes. Je veux dire:

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

Ce scénario est faux. Vous devez ensuite ajouter un fichier de valeur appelé peut-être ids.xml avec les éléments suivants:

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

Ensuite, dans votre classe, appelez:

 ...
 setTag(R.id.resourceDrawable, KEY_1)
 setTag(R.id.imageURI, KEY_2)
 ...
Sterling Diaz
la source
meilleure explication pour les nouveaux arrivants
Richard Le Mesurier
C'est la vraie solution: pas le correctif de hack newbie!
Roel
8
private static final int TAG_ONLINE_ID = 1 + 2 << 24;

devrait marcher. Plus d'informations de ceph3us :

La clé spécifiée doit être un identifiant déclaré dans les ressources de l'application pour garantir qu'il est unique. Les clés identifiées comme appartenant au framework Android ou associées à un package entraîneront la levée d'une IllegalArgumentException.

de la source:

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);
}
Anton Duzenko
la source
Parce que l'ID doit être celui généré dans votre fichier R.java.
StackOverflowed
Non. Il doit être supérieur à 2 << 24, c'est tout.
Anton Duzenko
Eh bien, l'approche 1 + 2 << 24, 2 + 2 << 24 etc. fonctionne réellement. On dirait une solution irrégulière. J'aime savoir pourquoi c'est comme ça? Existe-t-il des risques, par exemple dans les futures versions d'Android, etc.? Il est de loin plus étouffant de l'utiliser défini comme une constante?
Jan Bergström
Parce qu'il est codé en dur dans le SDK Android. Cela ne changera jamais car sinon toutes les applications Android existantes cesseront de fonctionner.
Anton Duzenko
1
Je suppose que le principal problème de cette solution est qu'elle ne garantit pas l'uniformité de cette clé, ce qui signifie qu'en ajoutant une bibliothèque ou un autre code utilisant la fonction setTag, cette logique peut se rompre si l'ID généré correspond à celui obtenu à partir de cette solution.
EdgarK du
3

J'ai utilisé viewHolder.itemTitleTextView.getId(). Mais vous pouvez également déclarer dans vos ressources: <item type="id" name="conversation_thread_id"/>

ViliusK
la source
0

Cela fonctionne pour moi:

setTag(0xffffffff,objContact.onlineid);
yu xiaofei
la source
0

La raison pour laquelle vous souhaitez enregistrer la valeur par un identifiant est que vous souhaitez couvrir plus d'une valeur dans cette balise, n'est-ce pas?
Voici une solution plus simple:
Supposons que vous souhaitiez enregistrer deux valeurs (Strings) dans cette balise: "firstname" et "lastname". Vous pouvez les enregistrer tous les deux dans une chaîne, séparés par un point-virgule:

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

... et accédez-y en les divisant en un tableau de chaînes:

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

vous pouvez utiliser ceci:

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

pour un identifiant de ressource spécifique à l'application uniqness

Jackie Cheng
la source