A chave deve ser um ID de recurso específico do aplicativo

145

Por que recebo essa exceção?

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)

a linha em questão é:

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

e eu tenho isso definido como:

private static final int TAG_ONLINE_ID = 1;
Pentium10
fonte

Respostas:

55

O ID da tag deve ser exclusivo para que ele seja criado em um arquivo de recursos para garantir a exclusividade.

Se a visualização contiver apenas uma tag, você poderá fazer

setTag(objContact.onlineid);
Robby Pond
fonte
3
eu ainda não entendi o padrão. Eu quero definir duas tags correspondentes para dizer um nome e sobrenome. onde eu defino os IDs inteiros para esses?
Jeffrey Blattman
7
Você pode usar qualquer recurso - até mesmo pegue um R.id.FOO aleatório, onde FOO é algum id no seu projeto.
Artem Russakovskii
16
Essa é a melhor maneira de obter um ID de tag exclusivo? Realmente Android?
jimmy0251
Olá, e se eu não souber quantas tags existem? porque eu quero gerar visualizações de acordo com alguns dados no modelo ....
jsina
Uma possível solução para o problema do solicitante, mas não é a melhor solução. Não deve ser marcado como a resposta ...
angryITguy
226

O motivo pelo qual você não é capaz de usar setTag (int, Object) é porque o Android exige um ID exclusivo pré-compilado no argumento 'int'.

Tente criar duas entradas exclusivas em String.xml xml, diga "primeiro nome" e "segundo nome" e use-as como abaixo

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");
ABDroids
fonte
129
adicione isso ao seu arquivo strings.xml: <item type = "id" name = "TAG_ONLINE_ID" /> e você pode usar como um recurso de identificação regular: R.id.TAG_ONLINE_ID
EtienneSky
9
este deve ser a resposta. é mais genérico.
IronBlossom
2
@AjithMemana why? Quando o aplicativo é compilado, o arquivo strings.xml atribui um ID de recurso int exclusivo para cada elemento. O valor do elemento string não é levado em consideração.
ataulm
1
Obrigado, que é tão grande e útil ... também se você deseja obter o tag que você precisa para valores cordas de acesso como v.getTag (R.string.name)
Amt87
5
É melhor criar um nome de arquivo ids.xml no diretório res / values e adicionar todos os seus IDs exclusivos.
vovahost
146

Estou um pouco atrasado para a festa, mas hoje me deparei com esse problema e pensei em dar uma resposta também. Esta resposta será um pouco de compilação das outras respostas, mas com um toque. Primeiro, o ID, como foi apontado por outras pessoas, NÃO pode ser uma constante definida no seu código (como estática privada final int MYID = 123) ou qualquer outro int que você defina como um campo em algum lugar.

O ID deve ser um ID exclusivo pré-compilado, assim como os obtidos por strings que você coloca em values ​​/ strings.xml (por exemplo, R.string.mystring). Consulte http://developer.android.com/guide/topics/resources/available-resources.html e http://developer.android.com/guide/topics/resources/more-resources.html para obter mais informações.

Minha sugestão é que você crie um novo arquivo chamado values ​​/ tags.xml e escreva:

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

Eu acho que é melhor criar um arquivo separado em vez de colocá-lo em strings.xml, como sugerido pelo EtienneSky.

britzl
fonte
14
Você pode até <item name="TAG_ONLINE_ID" type="id"/>simplificar.
Benoit Duffez
Esta é a solução real; Não é o novato "Eu não entendo o que estou fazendo, mas esse truque funciona" -solution
Roel
note, para acessar no uso de código R.id..., e não R.string.. ouR.tags...
g2server
Isso foi útil e aqui está outro post onde mostra seu uso: stackoverflow.com/questions/28492493/…
prasad_
E certifique-se de colocar o arquivo nos valores e não na pasta xml. :)
Nantoka
55

ISSO FAZ O TRABALHO ...

Se você tiver apenas 1 setTag em sua classe, poderá usar qualquer final int, talvez estático declarado no topo.

O problema surge quando você tinha 2 ou mais setTag's com chaves diferentes. Quero dizer:

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

Esse cenário está errado. Você precisará adicionar um arquivo de valor chamado talvez ids.xml com o seguinte:

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

Então, na sua turma, ligue para:

 ...
 setTag(R.id.resourceDrawable, KEY_1)
 setTag(R.id.imageURI, KEY_2)
 ...
Sterling Diaz
fonte
melhor explicação para os novatos
Richard Le Mesurier
Esta é a solução real: não a correção para iniciantes!
Roel
8
private static final int TAG_ONLINE_ID = 1 + 2 << 24;

Deveria trabalhar. Mais informações de ceph3us :

A chave especificada deve ser um ID declarado nos recursos do aplicativo para garantir que sejam chaves únicas identificadas como pertencentes à estrutura do Android ou não associadas a nenhum pacote, fazendo com que uma IllegalArgumentException seja lançada.

da fonte:

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
fonte
Porque o ID deve ser um gerado no seu arquivo R.java.
StackOverflowed
Não, não tem. Tem que ser maior que 2 << 24, só isso.
Anton Duzenko
Bem, a abordagem 1 + 2 << 24, 2 + 2 << 24 etc realmente funciona. Parece uma correção irregular. Eu gosto de saber por que é assim? Existem riscos, por exemplo, em versões futuras do Android, etc? É de longe sufocante usá-lo definido como uma constante?
Jan Bergström
Porque está codificado no SDK do Android. Isso nunca mudará porque, caso contrário, todos os aplicativos Android existentes deixarão de funcionar.
Anton Duzenko 17/02
1
Eu acho que o principal problema nesta solução é que ela não garante a unicidade da chave, o que significa que, ao adicionar alguma biblioteca ou outro código que esteja usando o recurso setTag, essa lógica poderá ser quebrada se o ID gerado corresponder ao obtido com essa solução.
EdgarK 27/09
3

Eu já usei viewHolder.itemTitleTextView.getId(). Mas você também pode declarar em seus recursos: <item type="id" name="conversation_thread_id"/>

ViliusK
fonte
0

Isso funciona para mim:

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

O motivo pelo qual você deseja salvar o valor por um ID é que deseja cobrir mais de um valor nessa tag, certo?
Aqui está uma solução mais simples:
digamos que você queira salvar dois valores (Strings) nessa tag: "firstname" e "lastname". Você pode salvar os dois em uma sequência, separada por ponto e vírgula:

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

... e acesse-os dividindo-os em uma matriz de strings:

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

você pode usar isso:

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

para identificação de recurso específico do aplicativo uniqness

Jackie Cheng
fonte