Mục đích chính của các phương thức ViewTag () getTag () là gì?


421

Mục đích chính của các phương thức như setTag()getTag()của Viewcác đối tượng kiểu là gì?

Tôi có đúng khi nghĩ rằng tôi có thể liên kết bất kỳ số lượng đối tượng nào với một Chế độ xem không?

Câu trả lời:


636

Giả sử bạn tạo ra một loạt các chế độ xem tương tự nhau. Bạn có thể đặt OnClickListenerriêng cho từng chế độ xem:

button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
 ...

Sau đó, bạn phải tạo một onClickphương thức duy nhất cho mỗi chế độ xem ngay cả khi chúng thực hiện những việc tương tự, như:

public void onClick(View v) {
    doAction(1); // 1 for button1, 2 for button2, etc.
}

Điều này là do onClickchỉ có một tham số, a Viewvà nó phải lấy thông tin khác từ các biến thể hiện hoặc biến cục bộ cuối cùng trong phạm vi kèm theo. Những gì chúng tôi thực sự muốn là để có được thông tin từ các quan điểm .

Nhập getTag/ setTag:

button1.setTag(1);
button2.setTag(2);

Bây giờ chúng tôi có thể sử dụng cùng một OnClickListener cho mọi nút:

listener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        doAction(v.getTag());
    }
};

Về cơ bản, đó là cách để các khung nhìn có ký ức .


8
@Matthew Willis nhưng chúng ta cũng có thể làm điều đó bằng cách sử dụng view.getId (). không phải nó ?
Kẻ giết người Android

50
@AndroidKiller bạn có thể, nhưng với setTag () bạn có thể đặt bất kỳ đối tượng nào bạn muốn, thậm chí các lớp tùy chỉnh - vì vậy bạn có thể sử dụng chúng để duy trì tham chiếu đến dữ liệu mà chế độ xem đang hiển thị
Daniel

Tôi nên làm gì nếu tôi chỉ muốn thay đổi màu nền của nút được nhấp ??? Tôi đang nhận được vị trí của getTag ().
Sagar Devanga

2
@Sagar: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }nên làm thủ thuật cho phần màu. 20 chỉ là một giữ chỗ cho vị trí xác thực của Chế độ xem của bạn.
RiA

Tôi nghĩ rằng đây là cách cũ. cách mới là sử dụng các đối số chung cung cấp loại an toàn. nhưng điều này vẫn tốt
M.kazem Akhÿ

124

Tôi muốn thêm vài từ.

Mặc dù việc sử dụng get/setTag(Object)dường như rất hữu ích trong trường hợp cụ thể của mẫu ViewHolder, tôi khuyên bạn nên suy nghĩ kỹ trước khi sử dụng nó trong các trường hợp khác. Hầu như luôn luôn có một giải pháp khác với thiết kế tốt hơn.

Lý do chính là mã như thế trở nên không được hỗ trợ khá nhanh.

  • Không rõ ràng đối với các nhà phát triển khác, những gì bạn đã thiết kế để lưu trữ dưới dạng thẻ trong chế độ xem. Các phương phápsetTag/getTag không được mô tả ở tất cả.

  • Nó chỉ lưu trữ một Object, mà cần phải được đúc khi bạn muốngetTag . Bạn có thể gặp sự cố không mong muốn sau này khi bạn quyết định thay đổi loại đối tượng được lưu trữ trong thẻ.

  • Đây là một câu chuyện thực tế: Chúng tôi đã có một dự án khá lớn với rất nhiều bộ điều hợp, hoạt động không đồng bộ với các khung nhìn, v.v. Một nhà phát triển đã quyết định set/getTagtrong phần mã của mình, nhưng một nhà phát triển khác đã đặt thẻ cho chế độ xem này. Cuối cùng, ai đó không thể tìm thấy thẻ của riêng mình và đã rất bối rối. Chúng tôi mất vài giờ để tìm ra lỗi.

setTag(int key, Object tag) trông tốt hơn nhiều, vì bạn có thể tạo các khóa duy nhất cho mỗi thẻ (sử dụng tài nguyên id ), nhưng có một hạn chế đáng kể cho Android <4.0. Từ tài liệu Lint:

Trước Android 4.0, việc triển khai View.setTag (int, Object) sẽ lưu trữ các đối tượng trong bản đồ tĩnh, trong đó các giá trị được tham chiếu mạnh mẽ. Điều này có nghĩa là nếu đối tượng chứa bất kỳ tham chiếu nào quay lại bối cảnh, bối cảnh (chỉ ra khá nhiều thứ khác) sẽ bị rò rỉ. Nếu bạn vượt qua một khung nhìn, khung nhìn cung cấp một tham chiếu đến bối cảnh đã tạo ra nó. Tương tự, chủ sở hữu chế độ xem thường chứa chế độ xem và con trỏ đôi khi cũng được liên kết với chế độ xem.


2
Cảm ơn, rất hữu ích! ... Bạn có tình cờ biết liệu những gì trong thẻ được khôi phục giữa các lần tái tạo hoạt động không?
súng ngắn

25

Chúng ta có thể sử dụng setTag()getTag()để thiết lập và nhận các đối tượng tùy chỉnh theo yêu cầu của chúng tôi. Các setTag()phương pháp có một đối số kiểu Object, và getTag()trả về mộtObject .

Ví dụ,

Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);

20

Đối với các nhà phát triển web, điều này dường như tương đương với dữ liệu- ..


14

Điều này rất hữu ích cho ArrayAdapterviệc sử dụng tùy chỉnh . Nó là một số loại tối ưu hóa. Đã setTagsử dụng làm tham chiếu đến đối tượng tham chiếu trên một số phần của bố cục (hiển thị trong ListView) thay vì findViewById.

static class ViewHolder {
    TextView tvPost;
    TextView tvDate;
    ImageView thumb;
}

public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        LayoutInflater inflater = myContext.getLayoutInflater();
        convertView = inflater.inflate(R.layout.postitem, null);

        ViewHolder vh = new ViewHolder();
        vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
        vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
        vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
        convertView.setTag(vh);
    }
            ....................
}

13

Không giống như ID, thẻ không được sử dụng để xác định chế độ xem. Các thẻ về cơ bản là một phần thông tin bổ sung có thể được liên kết với một khung nhìn. Chúng thường được sử dụng như một sự tiện lợi để lưu trữ dữ liệu liên quan đến các khung nhìn trong chính các khung nhìn thay vì đặt chúng vào một cấu trúc riêng biệt.

Tham khảo: http://developer.android.com/reference/android/view/View.html


11

Cài đặt TAG thực sự hữu ích khi bạn có ListView và muốn tái chế / tái sử dụng các chế độ xem. Theo cách đó, ListView đang trở nên rất giống với RecyclerView mới hơn.

@Override
public View getView(int position, View convertView, ViewGroup parent)
  {
ViewHolder holder = null;

if ( convertView == null )
{
    /* There is no view at this position, we create a new one. 
       In this case by inflating an xml layout */
    convertView = mInflater.inflate(R.layout.listview_item, null);  
    holder = new ViewHolder();
    holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
    convertView.setTag (holder);
}
else
{
    /* We recycle a View that already exists */
    holder = (ViewHolder) convertView.getTag ();
}

// Once we have a reference to the View we are returning, we set its values.

// Here is where you should set the ToggleButton value for this item!!!

holder.toggleOk.setChecked( mToggles.get( position ) );

return convertView;
}
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.