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.