Khóa phải là id tài nguyên dành riêng cho ứng dụng


145

Tại sao tôi có Ngoại lệ này?

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)

dòng trong câu hỏi là:

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

và tôi có nó được định nghĩa là:

private static final int TAG_ONLINE_ID = 1;

Câu trả lời:


55

Id thẻ phải là duy nhất để nó muốn là id được tạo trong tệp tài nguyên để đảm bảo tính duy nhất.

Nếu chế độ xem sẽ chỉ chứa một thẻ mặc dù bạn chỉ có thể làm

setTag(objContact.onlineid);

3
tôi vẫn không nhận được mô hình. tôi muốn đặt hai thẻ tương ứng để nói tên và họ. Tôi định nghĩa ID số nguyên cho những cái này ở đâu?
Jeffrey Blattman

7
Bạn có thể sử dụng bất kỳ tài nguyên nào - thậm chí chỉ cần lấy một R.id.FOO ngẫu nhiên trong đó FOO là một số id trong dự án của bạn.
Artem Russakovskii

16
Đó là cách tốt nhất để có id thẻ duy nhất? Android thực sự?
jimmy0251

Này, nếu tôi không biết có bao nhiêu thẻ thì sao? bởi vì tôi muốn tạo lượt xem theo một số dữ liệu trong mô hình ....
jsina

Một giải pháp khả thi cho vấn đề của người hỏi, nhưng không phải là giải pháp tốt nhất. Không nên được đánh dấu là câu trả lời ...
tức giậnITguy

226

Lý do bạn không thể sử dụng setTag (int, Object) là vì Android yêu cầu id duy nhất được biên dịch sẵn trong đối số 'int'.

Hãy thử tạo hai mục nhập duy nhất trong String.xml xml, nói "tên đầu tiên" và "tên thứ hai" và sử dụng chúng như dưới đây

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

129
thêm phần này vào tệp String.xml của bạn: <item type = "id" name = "TAG_ONLINE_ID" /> và bạn có thể sử dụng như một tài nguyên id thông thường: R.id.TAG_ONLINE_ID
EtienneSky

9
cái này nên là câu trả lời nó chung chung hơn.
IronBlieo

2
@AjithMemana tại sao? Khi ứng dụng được biên dịch, tệp String.xml sẽ gán một id tài nguyên int duy nhất cho mỗi phần tử. Giá trị của phần tử chuỗi không được tính đến.
ataulm

1
Cảm ơn bạn, điều đó thật tuyệt vời và hữu ích ... ngoài ra nếu bạn muốn nhận thẻ bạn cần truy cập các giá trị chuỗi như v.getTag (R.opes.name)
Amt87

5
Tốt hơn là tạo một tên tệp ids.xml trong thư mục res / value và thêm vào đó tất cả các id duy nhất của bạn.
vovahost

146

Tôi đến bữa tiệc muộn một chút nhưng tôi đã vấp phải vấn đề này ngày hôm nay và nghĩ rằng tôi cũng sẽ đưa ra câu trả lời. Câu trả lời này sẽ là một chút tổng hợp của các câu trả lời khác, nhưng với một twist. Trước hết, id, như đã được người khác chỉ ra, KHÔNG thể là hằng số được xác định trong mã của bạn (chẳng hạn như private static int MYID = 123) hoặc bất kỳ int nào khác mà bạn xác định là trường ở đâu đó.

Id phải là một id duy nhất được biên dịch sẵn, giống như các id bạn nhận được cho các chuỗi mà bạn đặt trong các giá trị / chuỗi.xml (tức là R. String.mystring). Tham khảo http://developer.android.com/guide/topics/resource/av Available-resource.htmlhttp://developer.android.com/guide/topics/resource/more-resource.html để biết thêm thông tin.

Đề nghị của tôi là bạn tạo một tệp mới gọi là value / tags.xml và viết:

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

Tôi nghĩ rằng tốt hơn là tạo một tệp riêng thay vì đặt nó trong chuỗi XML như EtienneSky đề xuất.


14
Bạn thậm chí có thể làm cho nó <item name="TAG_ONLINE_ID" type="id"/>để đơn giản hóa.
Benoit Duffez

Đây là giải pháp thực sự; Không phải người mới "Tôi không hiểu những gì tôi đang làm nhưng bản hack này hoạt động" - giải quyết
Roel

lưu ý, để truy cập trong việc sử dụng mã R.id..., và không R.string.. hoặcR.tags...
g2server

Điều này rất hữu ích và đây là một bài đăng khác cho thấy cách sử dụng của nó: stackoverflow.com/questions/28492493/ Lời
prasad_

Và hãy chắc chắn rằng bạn đặt tệp trong các giá trị chứ không phải trong thư mục xml. :)
Nantoka

55

ĐIỀU NÀY S DO LÀM VIỆC ...

Nếu bạn chỉ có 1 setTag trong lớp, bạn có thể sử dụng bất kỳ int, có thể là cuối cùng tĩnh được khai báo ở trên cùng.

Vấn đề xảy ra khi bạn có 2 setTag trở lên với các khóa khác nhau. Ý tôi là:

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

Kịch bản đó là sai. Sau đó, bạn cần thêm một tệp giá trị có thể là ids.xml bằng cách sau:

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

Sau đó, trong lớp của bạn, gọi:

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

giải thích tốt nhất cho người mới
Richard Le Mesurier

Đây là giải pháp thực sự: không phải bản sửa lỗi hack newbie!
Roel

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

nên làm việc. Thông tin thêm từ ceph3us :

Khóa được chỉ định phải là id được khai báo trong tài nguyên của ứng dụng để đảm bảo đó là Khóa duy nhất được xác định là thuộc khung Android hoặc không được liên kết với bất kỳ gói nào sẽ khiến IllegalArgumentException bị ném.

từ nguồn:

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

Bởi vì ID phải được tạo trong tệp R.java của bạn.
StackOverflow

Không nó không. Nó phải lớn hơn 2 << 24, chỉ vậy thôi.
Anton Duzenko

Chà, cách tiếp cận 1 + 2 << 24, 2 + 2 << 24 vv thực sự hoạt động. Trông giống như một sửa chữa bất thường. Tôi muốn biết tại sao nó lại như thế này? Có bất kỳ rủi ro nào, ví dụ như trong các phiên bản Android trong tương lai không? Nó là mịn hơn để sử dụng nó được định nghĩa là một hằng số?
Jan Bergström

Bởi vì nó được mã hóa cứng trong SDK Android. Nó sẽ không thay đổi bao giờ vì nếu không tất cả các ứng dụng Android hiện tại sẽ ngừng hoạt động.
Anton Duzenko

1
Tôi đoán vấn đề chính trong giải pháp này là nó không đảm bảo tính đơn nhất của khóa này, điều đó có nghĩa là bằng cách thêm một số thư viện hoặc mã khác đang sử dụng tính năng setTag, logic này có thể bị phá vỡ nếu id được tạo sẽ khớp với giải pháp này.
EdgarK

3

Tôi đã sử dụng viewHolder.itemTitleTextView.getId(). Nhưng bạn cũng có thể khai báo trong tài nguyên của mình: <item type="id" name="conversation_thread_id"/>


0

Điều này làm việc cho tôi:

setTag(0xffffffff,objContact.onlineid);

0

Lý do tại sao bạn muốn lưu giá trị bằng một id là, bạn muốn bao gồm nhiều hơn một giá trị trong thẻ này, phải không?
Đây là một giải pháp đơn giản hơn:
giả sử bạn muốn lưu hai giá trị (Chuỗi) vào thẻ này: "tên đầu tiên" và "tên cuối cùng". Bạn có thể lưu cả hai trong một chuỗi, cách nhau bằng dấu chấm phẩy:

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

... và truy cập chúng bằng cách chia chúng thành một chuỗi chuỗi:

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

0

bạn có thể sử dụng cái này:

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

đối với id tài nguyên dành riêng cho ứng dụng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.