Klucz musi być identyfikatorem zasobu specyficznym dla aplikacji


145

Dlaczego otrzymuję ten wyjątek?

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)

przedmiotowa linia to:

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

i mam to zdefiniowane jako:

private static final int TAG_ONLINE_ID = 1;

Odpowiedzi:


55

Identyfikator tagu musi być unikalny, więc chce, aby był to identyfikator utworzony w pliku zasobów w celu zagwarantowania unikalności.

Jeśli widok będzie zawierał tylko jeden tag, możesz to zrobić

setTag(objContact.onlineid);

3
nadal nie rozumiem wzoru. Chcę ustawić dwa tagi odpowiadające imieniu i nazwisku. gdzie mogę zdefiniować identyfikatory całkowite dla tych?
Jeffrey Blattman

7
Możesz użyć dowolnego zasobu - nawet po prostu weź losowy R.id.FOO, gdzie FOO to jakiś identyfikator w Twoim projekcie.
Artem Russakovskii

16
To najlepszy sposób na uzyskanie unikalnego identyfikatora tagu? Naprawdę Android?
jimmy0251

Hej, a co jeśli nie wiem, ile jest tagów? ponieważ chcę generować widoki na podstawie niektórych danych w modelu ....
jsina Kwietnia

Możliwe rozwiązanie problemu pytającego, ale nie jest to najlepsze rozwiązanie. Nie należy oznaczać jako odpowiedzi ...
angryITguy

226

Powodem, dla którego nie możesz użyć setTag (int, Object), jest to, że Android wymaga prekompilowanego unikalnego identyfikatora w argumencie „int”.

Spróbuj utworzyć dwa unikalne wpisy w String.xml xml, powiedz „imię” i „drugie imię” i użyj ich jak poniżej

imageView.setTag(R.string.firstname, "Abhishek");
imageView.setTag(R.string.lastname, "Gondalia");

129
dodaj to do swojego pliku strings.xml: <item type = "id" name = "TAG_ONLINE_ID" /> i możesz używać go jak zwykłego zasobu identyfikatora: R.id.TAG_ONLINE_ID
EtienneSky

9
ten powinien być odpowiedzią. jego bardziej ogólne.
IronBlossom,

2
@AjithMemana dlaczego? Gdy aplikacja jest kompilowana, plik strings.xml przypisuje każdemu elementowi unikalny identyfikator zasobu int. Wartość elementu string nie jest brana pod uwagę.
ataulm

1
Dziękuję, to jest świetne i pomocne ... także jeśli chcesz uzyskać tag, musisz uzyskać dostęp do wartości ciągów, takich jak v.getTag (R.string.name)
Amt87,

5
Lepiej utwórz nazwę pliku ids.xml w katalogu res / values i dodaj tam wszystkie swoje unikalne identyfikatory.
vovaost

146

Trochę się spóźniłem na imprezę, ale sam dzisiaj natknąłem się na ten problem i pomyślałem, że też dam odpowiedź. Ta odpowiedź będzie trochę kompilacją innych odpowiedzi, ale z pewnym elementem. Po pierwsze, id, jak wskazywali inni, NIE może być stałą zdefiniowaną w Twoim kodzie (np. Private static final int MYID = 123) ani żadną inną wartością typu int, którą zdefiniujesz gdzieś jako pole.

Identyfikator musi być prekompilowanym unikalnym identyfikatorem, tak jak te, które otrzymujesz dla łańcuchów, które umieszczasz w value / strings.xml (tj. R.string.mystring). Więcej informacji znajdziesz na http://developer.android.com/guide/topics/resources/available-resources.html i http://developer.android.com/guide/topics/resources/more-resources.html .

Moja sugestia jest taka, aby utworzyć nowy plik o nazwie values ​​/ tags.xml i napisać:

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

Myślę, że lepiej jest utworzyć osobny plik zamiast umieszczać go w strings.xml, jak sugerował EtienneSky.


14
Możesz nawet <item name="TAG_ONLINE_ID" type="id"/>uprościć to.
Benoit Duffez,

To jest prawdziwe rozwiązanie; Nie nowicjusz „Nie rozumiem, co robię, ale ten hack działa”
Roel

uwaga, aby uzyskać dostęp w użyciu kodu R.id..., a nie R.string.. lubR.tags...
g2server

Było to przydatne, a oto kolejny post, w którym pokazuje jego użycie: stackoverflow.com/questions/28492493/ ...
prasad_

I upewnij się, że umieściłeś plik w wartościach, a nie w folderze xml. :)
Nantoka

55

TO WYKONUJE PRACĘ ...

Jeśli masz tylko 1 setTag w swojej klasie, możesz użyć dowolnego typu int, może statycznego final zadeklarowanego na górze.

Problem pojawia się, gdy masz 2 lub więcej setTagów z różnymi kluczami. Mam na myśli:

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

Ten scenariusz jest zły. Następnie musisz dodać plik wartości o nazwie może ids.xml z następującymi elementami:

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

Następnie w klasie zadzwoń:

 ...
 setTag(R.id.resourceDrawable, KEY_1)
 setTag(R.id.imageURI, KEY_2)
 ...

najlepsze wytłumaczenie dla nowicjuszy
Richard Le Mesurier

To jest prawdziwe rozwiązanie: nie naprawa hacka dla początkujących!
Roel

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

powinno działać. Więcej informacji od ceph3us :

Określony klucz powinien być identyfikatorem zadeklarowanym w zasobach aplikacji, aby upewnić się, że jest unikalny. Klucze zidentyfikowane jako należące do platformy Android lub niepowiązane z żadnym pakietem spowodują wyrzucenie wyjątku IllegalArgumentException.

ze źródła:

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);
}

Ponieważ identyfikator musi być wygenerowany w pliku R.java.
StackOverflowed

Nie. Musi być większe niż 2 << 24, to wszystko.
Anton Duzenko

Cóż, podejście 1 + 2 << 24, 2 + 2 << 24 itd. Faktycznie działa. Wygląda na nieregularną poprawkę. Lubię wiedzieć, dlaczego tak jest? Czy są jakieś zagrożenia, na przykład w przyszłych wersjach Androida itp.? O wiele łatwiej jest używać go jako stałej?
Jan Bergström

Ponieważ jest zakodowany na stałe w Android SDK. To się nigdy nie zmieni, ponieważ w przeciwnym razie wszystkie istniejące aplikacje na Androida przestaną działać.
Anton Duzenko

1
Myślę, że głównym problemem w tym rozwiązaniu jest to, że nie gwarantuje ono unikalności tego klucza, co oznacza, że ​​dodając jakąś bibliotekę lub inny kod korzystający z funkcji setTag ta logika może się zepsuć, jeśli wygenerowany identyfikator będzie pasował do tego otrzymanego z tego rozwiązania.
EdgarK

3

Użyłem viewHolder.itemTitleTextView.getId(). Ale możesz również zadeklarować w swoich zasobach: <item type="id" name="conversation_thread_id"/>



0

Powodem, dla którego chcesz zapisać wartość przez identyfikator, jest to, że chcesz uwzględnić więcej niż jedną wartość w tym tagu, prawda?
Oto prostsze rozwiązanie:
powiedzmy, że chcesz zapisać dwie wartości (ciągi znaków) w tym tagu: „imię” i „nazwisko”. Możesz zapisać je oba w jednym ciągu, oddzielonym średnikiem:

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

... i uzyskaj do nich dostęp, dzieląc je na tablicę ciągów:

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

0

możesz użyć tego:

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

dla unikalności identyfikatora zasobu specyficznego dla aplikacji

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.