คีย์ต้องเป็นรหัสทรัพยากรเฉพาะแอปพลิเคชัน


145

เหตุใดฉันจึงได้รับข้อยกเว้นนี้

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)

บรรทัดในคำถามคือ:

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

และฉันได้กำหนดไว้เป็น:

private static final int TAG_ONLINE_ID = 1;

คำตอบ:


55

แท็ก id ต้องไม่ซ้ำกันดังนั้นจึงต้องการให้เป็น id ที่สร้างในไฟล์ทรัพยากรเพื่อรับประกันความเป็นเอกลักษณ์

หากมุมมองจะมีเพียงแท็กเดียว แต่คุณสามารถทำได้

setTag(objContact.onlineid);

3
ฉันยังไม่เข้าใจรูปแบบ ฉันต้องการตั้งค่าสองแท็กที่สอดคล้องกันเพื่อพูดชื่อและนามสกุล ฉันจะกำหนด ID จำนวนเต็มสำหรับสิ่งเหล่านี้ได้ที่ไหน
Jeffrey Blattman

7
คุณสามารถใช้ทรัพยากรใด ๆ - แม้เพียงแค่สุ่ม R.id.FOO โดยที่ FOO เป็นรหัสบางอย่างในโครงการของคุณ
Artem Russakovskii

16
นั่นเป็นวิธีที่ดีที่สุดในการรับ id แท็กที่ไม่ซ้ำกันใช่ไหม Android จริงเหรอ?
jimmy0251

เฮ้ถ้าฉันไม่รู้แท็กมีเท่าไหร่? เพราะผมต้องการสร้างมุมมองตามข้อมูลบางอย่างในรุ่น ....
jsina

วิธีแก้ไขที่เป็นไปได้สำหรับปัญหาของผู้ถาม แต่ไม่ใช่ทางออกที่ดีที่สุด ไม่ควรทำเครื่องหมายเป็นคำตอบ ...
โกรธITguy

226

เหตุผลที่คุณไม่สามารถใช้ setTag (int, Object) เป็นเพราะ Android ต้องการรหัสเฉพาะที่รวบรวมไว้ล่วงหน้าในอาร์กิวเมนต์ 'int'

ลองสร้างรายการที่ไม่ซ้ำกันสองรายการใน String.xml xml พูดว่า "firstname" & "secondname" และใช้พวกเขาดังต่อไปนี้

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

129
เพิ่มสิ่งนี้ลงในไฟล์ strings.xml ของคุณ: <item type = "id" name = "TAG_ONLINE_ID" /> และคุณสามารถใช้เช่นทรัพยากร id ปกติ: R.id.TAG_ONLINE_ID
EtienneSky

9
อันนี้ควรเป็นคำตอบ ทั่วไปมากขึ้น
IronBlossom

2
@AjithMemana ทำไม เมื่อรวบรวมแอปแล้วไฟล์ strings.xml จะกำหนดรหัสทรัพยากรเฉพาะให้กับแต่ละองค์ประกอบ มูลค่าขององค์ประกอบสตริงจะไม่นำมาพิจารณา
ataulm

1
ขอบคุณที่ยอดเยี่ยมและเป็นประโยชน์ ... นอกจากนี้หากคุณต้องการได้รับแท็กคุณจำเป็นต้องเข้าถึงค่าสตริงเช่น v.getTag (R.string.name)
Amt87

5
สร้างชื่อไฟล์ids.xmlในไดเรกทอรีres / valuesดีกว่าและเพิ่มรหัสเฉพาะของคุณทั้งหมด
vovahost

146

ฉันไปงานเลี้ยงเล็ก ๆ น้อย ๆ แต่ฉันก็พบปัญหานี้ด้วยตัวเองในวันนี้และคิดว่าฉันจะให้คำตอบเช่นกัน คำตอบนี้จะเป็นการรวบรวมคำตอบอื่น ๆ แต่เป็นการบิด ก่อนอื่นรหัสดังที่คนอื่นชี้ไม่สามารถกำหนดค่าคงที่ในรหัสของคุณ (เช่นส่วนตัวคงที่สุดท้าย MYID = 123) หรือ int อื่น ๆ ที่คุณกำหนดเป็นเขตบางแห่ง

ID ต้องเป็นรหัสเฉพาะที่คอมไพล์แล้วก่อนหน้าเช่นเดียวกับที่คุณได้รับจากสตริงที่คุณใส่ค่า / strings.xml (เช่น R.string.mystring) อ้างถึงhttp://developer.android.com/guide/topics/resources/available-resources.htmlและhttp://developer.android.com/guide/topics/resources/more-resources.htmlสำหรับข้อมูลเพิ่มเติม

คำแนะนำของฉันคือคุณสร้างไฟล์ใหม่ที่ชื่อว่า values ​​/ tags.xml และเขียน:

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

ฉันคิดว่าจะเป็นการดีกว่าถ้าสร้างไฟล์แยกต่างหากแทนที่จะวางไว้ใน strings.xml ตามที่ EtienneSky แนะนำ


14
คุณสามารถทำให้มัน<item name="TAG_ONLINE_ID" type="id"/>ง่ายขึ้นได้
เบอนัวต์ดัฟเช่

นี่คือทางออกที่แท้จริง ไม่ใช่มือใหม่ "ฉันไม่เข้าใจสิ่งที่ฉันกำลังทำอยู่ แต่แฮ็คนี้ใช้งานได้" - การแก้ไข
Roel

หมายเหตุเพื่อเข้าถึงการใช้รหัสR.id...และไม่ใช่ R.string..หรือR.tags...
g2server

นี่เป็นประโยชน์และนี่เป็นอีกโพสต์ที่แสดงการใช้งาน: stackoverflow.com/questions/28492493/…
prasad_

และให้แน่ใจว่าคุณใส่ไฟล์ในค่าและไม่ได้อยู่ในโฟลเดอร์ xml :)
Nantoka

55

งานนี้จะทำ ...

หากคุณมี 1 setTag ในชั้นเรียนของคุณคุณสามารถใช้ int ใด ๆ ก็ได้ซึ่งอาจจะเป็นครั้งสุดท้ายที่ประกาศไว้ด้านบน

ปัญหาเกิดขึ้นเมื่อคุณมี setTag 2 อันขึ้นไปพร้อมกับคีย์ที่แตกต่างกัน ฉันหมายถึง:

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

สถานการณ์นั้นผิด จากนั้นคุณต้องเพิ่มไฟล์ค่าที่ชื่อว่าบางที ids.xml ด้วยรายการต่อไปนี้:

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

จากนั้นในชั้นเรียนของคุณโทร:

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

คำอธิบายที่ดีที่สุดสำหรับผู้มาใหม่
Richard Le Mesurier

นี่คือทางออกที่แท้จริง: ไม่ใช่การแก้ไขแฮ็คมือใหม่!
Roel

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

ควรทำงาน. ข้อมูลเพิ่มเติมจากceph3us :

รหัสที่ระบุควรเป็นรหัสที่ประกาศในทรัพยากรของแอปพลิเคชันเพื่อให้แน่ใจว่าเป็นรหัสที่ไม่ซ้ำกันซึ่งระบุว่าเป็นของกรอบงาน Android หรือไม่เกี่ยวข้องกับแพคเกจใด ๆ จะทำให้เกิด IllegalArgumentException

จากแหล่งที่มา:

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

เนื่องจาก ID จะต้องเป็นรหัสที่สร้างในไฟล์ R.java ของคุณ
StackOverflow

ไม่มันไม่ มันจะต้องมีค่ามากกว่า 2 << 24 นั่นคือทั้งหมด
Anton Duzenko

วิธีการ 1 + 2 << 24, 2 + 2 << 24 ฯลฯ วิธีการใช้งานได้ผลจริง ดูเหมือนการแก้ไขที่ผิดปกติ ฉันชอบที่จะรู้ว่าทำไมมันเป็นเช่นนี้? มีความเสี่ยงหรือไม่ตัวอย่างเช่นใน Android รุ่นอนาคตหรือไม่ มันใช้วิธีการกำหนดค่าคงที่หรือไม่?
Jan Bergström

เพราะมันเป็นรหัสใน Android SDK มันจะไม่เปลี่ยนแปลงเลยเพราะมิฉะนั้นแอพ Android ที่มีอยู่ทั้งหมดจะหยุดทำงาน
Anton Duzenko

1
ฉันเดาว่าปัญหาหลักในการแก้ปัญหานี้คือมันไม่รับประกัน uniqness ของคีย์นี้ซึ่งหมายความว่าโดยการเพิ่มห้องสมุดหรือรหัสอื่น ๆ ที่ใช้คุณสมบัติ setTag ตรรกะนี้สามารถทำลายถ้ารหัสที่สร้างขึ้นจะตรงกับที่ได้มาจากวิธีนี้
EdgarK

3

viewHolder.itemTitleTextView.getId()ผมเคยใช้ แต่คุณสามารถประกาศในแหล่งข้อมูลของคุณ: <item type="id" name="conversation_thread_id"/>



0

เหตุผลที่คุณต้องการบันทึกค่าด้วยรหัสคือคุณต้องการครอบคลุมมากกว่าหนึ่งค่าในแท็กนี้ใช่ไหม
นี่คือวิธีแก้ปัญหาที่ง่ายกว่านี้:
สมมติว่าคุณต้องการบันทึกสองค่า (Strings) ลงในแท็กนี้: "firstname" และ "lastname" คุณสามารถบันทึกได้ทั้งสองในหนึ่งสายคั่นด้วยเครื่องหมายอัฒภาค:

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

... และเข้าถึงได้โดยแยกออกเป็นอาเรย์สตริง:

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

0

คุณสามารถใช้สิ่งนี้:

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

สำหรับรหัสทรัพยากรเฉพาะแอปพลิเคชัน uniqness

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.