วัตถุประสงค์หลักของ setTag () วิธี getTag () ของ View คืออะไร?


421

วัตถุประสงค์หลักของวิธีการเช่นคืออะไรsetTag()และgetTag()ของViewประเภทวัตถุ?

ฉันคิดถูกแล้วว่าฉันสามารถเชื่อมโยงวัตถุจำนวนมากกับมุมมองเดียวได้หรือไม่

คำตอบ:


636

สมมติว่าคุณสร้างมุมมองที่คล้ายกัน คุณสามารถตั้งค่าOnClickListenerสำหรับแต่ละมุมมองทีละรายการ:

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

จากนั้นคุณต้องสร้างonClickวิธีการเฉพาะสำหรับแต่ละมุมมองแม้ว่าพวกเขาจะทำสิ่งที่คล้ายกันเช่น:

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

เนื่องจากonClickมีเพียงหนึ่งพารามิเตอร์ a Viewและต้องรับข้อมูลอื่นจากตัวแปรอินสแตนซ์หรือตัวแปรโลคัลสุดท้ายในขอบเขตการล้อมรอบ สิ่งที่เราต้องการจริงๆคือการได้รับข้อมูลจากมุมมองของตัวเอง

ใส่getTag/ setTag:

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

ตอนนี้เราสามารถใช้ OnClickListener เดียวกันสำหรับทุกปุ่ม:

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

มันเป็นพื้นทางสำหรับมุมมองที่จะมีความทรงจำ


8
@ Matthews Willis แต่เราสามารถทำได้โดยใช้ view.getId () ด้วย มันไม่ได้เป็น ?
Android Killer

50
@AndroidKiller คุณทำได้ แต่ด้วย setTag () คุณสามารถใส่วัตถุใด ๆ ที่คุณต้องการแม้กระทั่งคลาสที่กำหนดเอง - เพื่อให้คุณสามารถใช้พวกเขาเพื่อยืนยันการอ้างอิงถึงข้อมูลที่มุมมองแสดงอยู่
Daniel

ฉันควรทำอย่างไรหากฉันต้องการเปลี่ยนสีพื้นหลังของปุ่มที่คลิกเท่านั้น ฉันได้รับตำแหน่งโดย getTag ()
Sagar Devanga

2
@ ซาการ์: public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }ควรทำเคล็ดลับสำหรับส่วนสี 20 เป็นเพียงตัวยึดตำแหน่งสำหรับการตรวจสอบตำแหน่งของมุมมองของคุณ
RiA

ฉันคิดว่านี่เป็นวิธีเก่า วิธีใหม่คือการใช้ข้อโต้แย้งทั่วไปที่ให้ความปลอดภัยประเภท แต่นี่เป็นสิ่งที่ดี
M.kazem Akhgary

124

ฉันต้องการเพิ่มคำไม่กี่คำ

แม้ว่าการใช้get/setTag(Object)ดูเหมือนจะมีประโยชน์มากในบางกรณีของรูปแบบ ViewHolder แต่ฉันขอแนะนำให้คิดสองครั้งก่อนใช้ในกรณีอื่น มีอีกวิธีการแก้ปัญหาอีกด้วยการออกแบบที่ดีกว่า

สาเหตุหลักคือรหัสเช่นนั้นจะไม่สามารถรับได้อย่างรวดเร็ว

  • ไม่ชัดเจนนักพัฒนาคนอื่น ๆ ที่คุณออกแบบไว้เพื่อเก็บเป็นแท็กในมุมมอง วิธีการsetTag/getTagไม่ได้อธิบายเลย

  • มันก็จัดเก็บซึ่งจะต้องมีและต้องถูกทิ้งเมื่อคุณต้องการObject getTagคุณสามารถรับความผิดพลาดที่ไม่คาดคิดได้ในภายหลังเมื่อคุณตัดสินใจเปลี่ยนประเภทของวัตถุที่เก็บไว้ในแท็ก

  • นี่คือเรื่องราวในชีวิตจริง: เรามีโครงการขนาดใหญ่ที่มีอะแดปเตอร์จำนวนมากการดำเนินการแบบอะซิงก์พร้อมมุมมองและอื่น ๆ ผู้พัฒนารายหนึ่งตัดสินใจที่จะใช้รหัสset/getTagในส่วนของเขา แต่อีกคนหนึ่งได้ตั้งค่าแท็กเป็นมุมมองนี้แล้ว ในท้ายที่สุดคนไม่สามารถหาแท็กของเขาเองและสับสนมาก มีค่าใช้จ่ายเราหลายชั่วโมงในการค้นหาข้อผิดพลาด

setTag(int key, Object tag)ดูดีขึ้นมากทำให้คุณสามารถสร้างคีย์ที่ไม่ซ้ำกันสำหรับทุกแท็ก (โดยใช้ทรัพยากร id ) แต่มีข้อ จำกัด ที่สำคัญสำหรับ Android <4.0 จาก Lint docs:

ก่อนหน้า Android 4.0 การใช้งาน View.setTag (int, Object) จะเก็บวัตถุไว้ในแผนที่แบบคงที่ซึ่งมีการอ้างอิงค่าอย่างมาก ซึ่งหมายความว่าหากวัตถุนั้นมีการอ้างอิงใด ๆ ที่ชี้ไปที่บริบทบริบท (ซึ่งชี้ไปที่ทุกสิ่งอื่น ๆ ) จะรั่วไหล หากคุณผ่านมุมมองมุมมองจะให้การอ้างอิงกับบริบทที่สร้างขึ้น ในทำนองเดียวกันผู้ถือมุมมองมักจะมีมุมมองและเคอร์เซอร์บางครั้งก็เชื่อมโยงกับมุมมอง


2
ขอบคุณมีประโยชน์มาก! ... คุณรู้หรือไม่ว่ามีสิ่งใดในแท็กที่ได้รับการกู้คืนระหว่างการจัดกิจกรรมใหม่?
gunar

25

เราสามารถใช้setTag()และgetTag()การตั้งค่าและรับวัตถุที่กำหนดเองตามความต้องการของเรา setTag()วิธีใช้อาร์กิวเมนต์พิมพ์Objectและส่งกลับgetTag()Object

ตัวอย่างเช่น,

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


14

สิ่งนี้มีประโยชน์มากสำหรับการArrayAdapterใช้งานที่กำหนดเอง เป็นการเพิ่มประสิทธิภาพบางอย่าง มีsetTagใช้เป็นข้อมูลอ้างอิงไปยังวัตถุที่อ้างอิงในบางส่วนของรูปแบบ (ที่แสดงในListView) 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

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

การอ้างอิง: http://developer.android.com/reference/android/view/View.html


11

การตั้งค่า TAG นั้นมีประโยชน์จริง ๆ เมื่อคุณมี ListView และต้องการรีไซเคิล / นำมุมมองนั้นมาใช้ซ้ำ ด้วยวิธีนี้ ListView จะคล้ายกับ RecyclerView รุ่นใหม่กว่ามาก

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