La clave debe ser un ID de recurso específico de la aplicación

145

¿Por qué obtengo esta excepción?

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 línea en cuestión es:

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

y lo tengo definido como:

private static final int TAG_ONLINE_ID = 1;
Pentium10
fuente

Respuestas:

55

La identificación de la etiqueta debe ser única, por lo que quiere que sea una identificación creada en un archivo de recursos para garantizar la unicidad.

Si la vista solo contendrá una etiqueta, solo puede hacer

setTag(objContact.onlineid);
Estanque Robby
fuente
3
Todavía no entiendo el patrón. Quiero establecer dos etiquetas correspondientes para decir un nombre y apellido. ¿Dónde defino los ID enteros para estos?
Jeffrey Blattman
77
Puede usar cualquier recurso, incluso tomar un R.id.FOO aleatorio donde FOO es una identificación en su proyecto.
Artem Russakovskii
16
¿Esa es la mejor manera de obtener una identificación de etiqueta única? ¿De verdad Android?
jimmy0251
Hola, ¿y si no sé cuántas etiquetas hay? porque quiero generar puntos de vista de acuerdo a algunos datos en el modelo ....
jsina
Una posible solución al problema del autor de la pregunta, pero no es la mejor solución. No debe marcarse como la respuesta ...
angryITguy
226

La razón por la que no puede usar setTag (int, Object) es porque Android requiere una identificación única precompilada en el argumento 'int'.

Intente crear dos entradas únicas en String.xml xml, diga "nombre" y "segundo nombre" y utilícelas como se muestra a continuación

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");
ABDroids
fuente
129129
agregue esto a su archivo strings.xml: <item type = "id" name = "TAG_ONLINE_ID" /> y puede usarlo como un recurso de identificación normal: R.id.TAG_ONLINE_ID
EtienneSky
9
Esta debería ser la respuesta. Es más genérico.
IronBlossom
2
@AjithMemana ¿por qué? Cuando se compila la aplicación, el archivo strings.xml asigna una identificación de recurso int única a cada elemento. El valor del elemento de cadena no se tiene en cuenta.
ataulm
1
Gracias, eso es genial y útil ... también si desea obtener la etiqueta que necesita para acceder a valores de cadenas como v.getTag (R.string.name)
Amt87
55
Mejor cree un nombre de archivo ids.xml en el directorio res / values y agregue allí todos sus identificadores únicos.
vovahost
146

Llego un poco tarde a la fiesta, pero hoy me topé con este problema y pensé que también daría una respuesta. Esta respuesta será una compilación de las otras respuestas, pero con un giro. En primer lugar, la identificación, como lo han señalado otros, NO puede ser una constante definida en su código (como int privado estático final MYID = 123) o cualquier otra int que defina como un campo en alguna parte.

La identificación debe ser una identificación única precompilada, al igual que las que obtiene para las cadenas que coloca en valores / strings.xml (es decir, R.string.mystring). Consulte http://developer.android.com/guide/topics/resources/available-resources.html y http://developer.android.com/guide/topics/resources/more-resources.html para obtener más información.

Mi sugerencia es que cree un nuevo archivo llamado values ​​/ tags.xml y escriba:

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

Creo que es mejor crear un archivo separado en lugar de ponerlo en strings.xml como EtienneSky sugirió.

britzl
fuente
14
Incluso puedes hacerlo <item name="TAG_ONLINE_ID" type="id"/>para simplificar.
Benoit Duffez
Esta es la verdadera solución; No es el novato "No entiendo lo que estoy haciendo, pero este truco funciona" -solución
Roel
nota, para acceder en el uso del código R.id..., y no R.string.. oR.tags...
g2server
Esto fue útil y aquí hay otra publicación donde muestra su uso: stackoverflow.com/questions/28492493/…
prasad_
Y asegúrese de colocar el archivo en los valores y no en la carpeta xml. :)
Nantoka
55

ESTO HARÁ EL TRABAJO ...

Si solo tiene 1 setTag en su clase, puede usar cualquier int, tal vez estático final declarado en la parte superior.

El problema surge cuando tenías 2 o más setTag's con diferentes claves. Quiero decir:

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

Ese escenario está mal. Luego debe agregar un archivo de valor llamado quizás ids.xml con lo siguiente:

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

Luego, en tu clase, llama al:

 ...
 setTag(R.id.resourceDrawable, KEY_1)
 setTag(R.id.imageURI, KEY_2)
 ...
Sterling Diaz
fuente
mejor explicación para los recién llegados
Richard Le Mesurier
Esta es la solución real: ¡no la solución para hackear a los novatos!
Roel
8
private static final int TAG_ONLINE_ID = 1 + 2 << 24;

Deberia trabajar. Más información de ceph3us :

La clave especificada debe ser una identificación declarada en los recursos de la aplicación para garantizar que sea única. Las claves identificadas como pertenecientes al marco de Android o no asociadas a ningún paquete provocarán una IllegalArgumentException.

de fuente:

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
fuente
Porque la ID debe ser una generada en su archivo R.java.
StackOverflowed
No, no lo hace. Tiene que ser mayor que 2 << 24, eso es todo.
Anton Duzenko
Bueno, el enfoque 1 + 2 << 24, 2 + 2 << 24 etc. realmente funciona. Parece una solución irregular. Me gusta saber por qué es así. ¿Hay algún riesgo, por ejemplo, en futuras versiones de Android, etc.? ¿Es mucho más sofocante usarlo definido como una constante?
Jan Bergström
Porque está codificado en Android SDK. Nunca cambiará porque, de lo contrario, todas las aplicaciones de Android existentes dejarán de funcionar.
Anton Duzenko
1
Supongo que el principal problema en esta solución es que no garantiza la uniformidad de esta clave, lo que significa que al agregar alguna biblioteca u otro código que esté usando la función setTag, esta lógica puede romperse si la identificación generada coincidirá con la obtenida de esta solución.
EdgarK
3

He usado viewHolder.itemTitleTextView.getId(). Pero también puedes declarar en tus recursos: <item type="id" name="conversation_thread_id"/>

ViliusK
fuente
0

Esto funciona para mi:

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

La razón por la que desea guardar el valor mediante una identificación es que desea cubrir más de un valor en esta etiqueta, ¿verdad?
Aquí una solución más simple:
supongamos que desea guardar dos valores (cadenas) en esta etiqueta: "nombre" y "apellido". Puede guardarlos en una cadena, separados por punto y coma:

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

... y acceder a ellos dividiéndolos en una matriz de cadenas:

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

puedes usar esto:

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

para uniqness id. de recurso específico de la aplicación

Jackie Cheng
fuente