Anahtar, uygulamaya özel bir kaynak kimliği olmalıdır


146

Neden bu İstisnayı alıyorum?

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)

söz konusu satır:

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

ve şu şekilde tanımladım:

private static final int TAG_ONLINE_ID = 1;

Yanıtlar:


55

Etiket kimliği benzersiz olmalıdır, bu nedenle benzersizliği garanti etmek için bir kaynaklar dosyasında oluşturulan bir kimlik olmasını ister.

Görünüm yalnızca bir etiket içerecekse, ancak bunu yapabilirsiniz

setTag(objContact.onlineid);

3
Hâlâ kalıbı anlamadım. Adı ve soyadını söyleyen iki etiket ayarlamak istiyorum. bunlar için tamsayı kimliklerini nerede tanımlarım?
Jeffrey Blattman

7
Herhangi bir kaynağı kullanabilirsiniz - hatta FOO'nun projenizde bir kimlik olduğu rastgele bir R.id.FOO alın.
Artem Russakovskii

18
Benzersiz etiket kimliği almanın en iyi yolu bu mu? Gerçekten Android mi?
jimmy0251

Hey, ya kaç etiket olduğunu bilmiyorsam? çünkü modeldeki bazı verilere göre görünümler oluşturmak istiyorum ....
jsina

Soruyu soranın sorununa olası bir çözüm, ancak en iyi çözüm değil. Cevap olarak işaretlenmemelidir ...
angryITguy

228

SetTag (int, Object) kullanamamanızın nedeni, android'in 'int' bağımsız değişkeninde önceden derlenmiş benzersiz bir kimlik gerektirmesidir.

String.xml xml'de "ad" ve "ikinci ad" gibi iki benzersiz giriş oluşturmayı deneyin ve bunları aşağıdaki gibi kullanın

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

132
bunu strings.xml dosyanıza ekleyin: <item type = "id" name = "TAG_ONLINE_ID" /> ve normal bir kimlik kaynağı gibi kullanabilirsiniz: R.id.TAG_ONLINE_ID
EtienneSky

9
cevap bu olmalı. daha genel.
IronBlossom

2
@AjithMemana neden? Uygulama derlendiğinde, strings.xml dosyası her öğeye benzersiz bir int kaynak kimliği atar. Dize öğesinin değeri dikkate alınmaz.
ataulm

1
Teşekkürler, bu harika ve yararlı ... ayrıca etiketi almak istiyorsanız v.getTag (R.string.name)
Amt87

5
Daha iyi bir dosya adı oluşturmak ids.xml içinde res / values dizini ve orada tüm benzersiz kimlikleri ekleyin.
vovahost

146

Partiye biraz geç kaldım ama bugün bu soruna kendim rastladım ve bir cevap vereceğimi düşündüm. Bu cevap, diğer cevapların bir derlemesi olacak, ancak biraz farklı olacak. Her şeyden önce, id, başkaları tarafından da belirtildiği gibi, kodunuzda tanımlanmış bir sabit (özel statik final int MYID = 123 gibi) veya bir yerde alan olarak tanımladığınız başka herhangi bir int OLAMAZ.

Kimlik, tıpkı values ​​/ strings.xml (yani R.string.mystring) içine koyduğunuz dizeler için aldığınız gibi, önceden derlenmiş benzersiz bir kimlik olmalıdır. Daha fazla bilgi için http://developer.android.com/guide/topics/resources/available-resources.html ve http://developer.android.com/guide/topics/resources/more-resources.html adreslerine bakın .

Önerim, values ​​/ tags.xml adlı yeni bir dosya oluşturup şunu yazmanızdır:

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

EtienneSky'nin önerdiği gibi strings.xml'ye koymak yerine ayrı bir dosya oluşturmanın daha iyi olacağını düşünüyorum.


14
Hatta <item name="TAG_ONLINE_ID" type="id"/>basitleştirmek için bile yapabilirsiniz .
Benoit Duffez

Gerçek çözüm budur; Acemi değil "Ne yaptığımı anlamıyorum ama bu hack işe yarıyor" -çözüm
Roel

1
kodu kullanılıyor erişmek için, dikkat R.id...ve değil R.string.. yaR.tags...
g2server

Bu yararlıydı ve işte kullanımını gösterdiği başka bir gönderi: stackoverflow.com/questions/28492493/…
prasad_

Ve dosyayı xml klasörüne değil değerlere koyduğunuzdan emin olun. :)
Nantoka

55

BU İŞİ YAPACAK ...

Sınıfınızda sadece 1 setTag varsa, herhangi bir int, belki de en üstte belirtilen statik final kullanabilirsiniz.

Sorun, farklı anahtarlara sahip 2 veya daha fazla setTag'iniz olduğunda ortaya çıkar. Demek istediğim:

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

Bu senaryo yanlış. Daha sonra, belki ids.xml adında aşağıdakileri içeren bir değer dosyası eklemeniz gerekir:

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

Ardından, sınıfınızda şu numarayı arayın:

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

yeni gelenler için en iyi açıklama
Richard Le Mesurier

Gerçek çözüm bu: acemi hack düzeltmesi değil!
Roel

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

çalışmalı. Ceph3us'tan daha fazla bilgi :

Belirtilen anahtar, benzersiz olduğundan emin olmak için uygulamanın kaynaklarında bildirilen bir kimlik olmalıdır.Android çerçevesine ait olduğu veya herhangi bir paketle ilişkili olmadığı belirlenen Anahtarlar, bir IllegalArgumentException atılmasına neden olacaktır.

kaynaktan:

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

Çünkü ID, R.java dosyanızda oluşturulmuş bir kimlik olmalıdır.
StackOverflow

Hayır değil. 2 << 24'ten büyük olmalı, hepsi bu.
Anton Duzenko

Aslında 1 + 2 << 24, 2 + 2 << 24 vb. Yaklaşım işe yarıyor. Düzensiz bir düzeltme gibi görünüyor. Neden böyle olduğunu bilmek isterim? Örneğin Android'in gelecekteki sürümlerinde herhangi bir risk var mı? Onu sabit olarak kullanmak çok daha yumuşak mı?
Jan Bergström

Çünkü Android SDK'da kodlanmıştır. Hiç değişmeyecek çünkü aksi takdirde mevcut tüm android uygulamaları çalışmayı durduracak.
Anton Duzenko

1
Sanırım bu çözümdeki ana sorun, bu anahtarın benzersizliğini garanti etmemesidir, yani setTag özelliğini kullanan bazı kitaplık veya başka bir kod ekleyerek, oluşturulan id bu çözümden elde edilenle eşleşecekse bu mantığın bozulabileceği anlamına gelir.
EdgarK

3

Kullandım viewHolder.itemTitleTextView.getId(). Ancak kaynaklarınızda şunları da beyan edebilirsiniz: <item type="id" name="conversation_thread_id"/>


0

Bu benim için çalışıyor:

setTag(0xffffffff,objContact.onlineid);

0

Değeri bir id ile kaydetmek istemenizin nedeni, bu etikette birden fazla değeri kapsamak istemeniz, değil mi?
Burada daha basit bir çözüm:
Diyelim ki bu etikete iki değer (Dizeler) kaydetmek istiyorsunuz: "ad" ve "soyad". Her ikisini de noktalı virgülle ayırarak tek bir dizede kaydedebilirsiniz:

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

... ve onları bir dizge dizisine bölerek onlara erişin:

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

0

bunu kullanabilirsiniz:

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

benzersizlik için uygulamaya özel kaynak kimliği


0

İşte benim için çalışan basit bir çözüm:

int tagKey = "YourSimpleKey".hashCode();

myView.setTag(tagKey, "MyTagObject");

Buradaki önemli ipucu .hashCode();, dizeyi aramaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.