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


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.