วิธี getViewTypeCount และ getItemViewType ของ ArrayAdapter


159

ใครบางคนในคำธรรมดาสามารถอธิบายการใช้getViewTypeCount()และgetItemViewType()วิธีการของArrayAdapterฉันได้ไหม

คำตอบ:


308

สิ่งเหล่านี้จัดการกับเคสที่คุณต้องการมุมมองประเภทต่างๆสำหรับแถวที่แตกต่างกัน ตัวอย่างเช่นในแอปพลิเคชันผู้ติดต่อคุณอาจต้องการให้แม้แต่แถวมีรูปภาพทางด้านซ้ายและแถวคี่เพื่อให้รูปภาพอยู่ด้านขวา ในกรณีนั้นคุณจะใช้:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

กรอบการใช้ประเภทมุมมองของคุณในการตัดสินใจซึ่งมุมมองที่จะถึงมือคุณทางconvertViewของคุณในgetViewวิธีการ กล่าวอีกนัยหนึ่งในตัวอย่างข้างต้นแถวคู่ของคุณจะได้รับมุมมองการรีไซเคิลที่มีรูปภาพทางด้านซ้ายเพื่อนำมาใช้ซ้ำและแถวคี่จะได้รับเฉพาะรูปภาพที่ด้านขวาเท่านั้น

หากทุกแถวในรายการของคุณมีเค้าโครงเหมือนกันคุณไม่จำเป็นต้องกังวลเกี่ยวกับประเภทมุมมอง ในความเป็นจริงBaseAdapter.javaจัดเตรียมพฤติกรรมเริ่มต้นสำหรับอะแดปเตอร์ทั้งหมด:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

นี่จะให้ประเภทการดูเหมือนกันสำหรับทุกแถว

แก้ไข - เพื่อร่างการไหลทั่วไป:

  1. คุณผูกข้อมูลกับAdapterViewอะแดปเตอร์ของคุณ
  2. ความAdapterViewพยายามที่จะแสดงรายการที่ผู้ใช้สามารถมองเห็นได้
  3. เฟรมเวิร์กร้องขอgetItemViewTypeแถวnแถวที่กำลังจะแสดง
  4. ตรวจสอบกรอบการมองเห็นวิวของสระว่ายน้ำกลับมาใช้ใหม่สำหรับมุมมองของแถวn's ประเภท ไม่พบใด ๆ เนื่องจากยังไม่มีการรีไซเคิลมุมมอง
  5. getViewnจะเรียกแถว
  6. คุณเรียกgetItemViewTypeใช้แถวnเพื่อกำหนดประเภทของมุมมองที่คุณควรใช้
  7. คุณใช้คำสั่ง if / switch เพื่อขยายไฟล์ xml อื่นขึ้นอยู่กับประเภทของมุมมองที่ต้องการ
  8. คุณกรอกข้อมูลด้วยมุมมอง
  9. คุณส่งคืนมุมมองออกgetViewและมุมมองแถวของคุณจะปรากฏต่อผู้ใช้

ตอนนี้เมื่อมุมมองถูกรีไซเคิลโดยการเลื่อนหน้าจอมันจะเข้าสู่กลุ่มมุมมองการรีไซเคิลที่จัดการโดยกรอบงาน สิ่งเหล่านี้ถูกจัดเรียงตามประเภทมุมมองเพื่อให้มุมมองประเภทที่ถูกต้องมอบให้คุณในconvertViewพารามิเตอร์ในgetViewวิธีการของคุณ:

  1. กรอบงานเรียกร้องgetItemViewTypeให้แถวที่ต้องการแสดงอีกครั้ง
  2. เวลานี้มีมุมมองในประเภทการรีไซเคิลที่เหมาะสม
  3. มุมมองที่นำกลับมาใช้จะถูกส่งถึงคุณเป็นconvertViewพารามิเตอร์ในgetViewวิธีการของคุณ
  4. คุณเติมข้อมูลใหม่ให้กับมุมมองรีไซเคิลแล้วส่งคืน

1
@ Matewew ขอบคุณสำหรับคำตอบของคุณ คุณช่วยอธิบายการไหลของวิธีการเหล่านี้ได้อย่างไร นอกจากนี้ฉันไม่เข้าใจว่าสิ่งนี้เกี่ยวข้องกับข้อมูลของฉันอย่างไรใน res / layout
Eugene

ไม่มีสัญญาที่ชัดเจนสำหรับเมื่อวิธีการเหล่านี้จะถูกเรียก res / layout เป็นสถานที่สำหรับดูวัตถุ นี้เป็นอะแดปเตอร์ คุณควรตรวจสอบประเภทรายการในวิธี getView ของคุณและขยายมุมมองที่เหมาะสมจากความละเอียด / เค้าโครง
Matthew Willis

1
คุณจะส่งคืนด้วยตัวคุณเองใน getItemViewType
Matthew Willis

คุณทำการเชื่อมโยงด้วยตนเองใน getView: ถ้า (พิมพ์ == 0) {/ * พอง R.layout.row_icon_on_left /} อื่น {/ขยาย R.layout.row_icon_on_right * /}
Matthew Willis

75
ระวัง! getItemViewType () จะต้องส่งคืนค่า int ระหว่าง 0 ถึง getViewTypeCount () - 1
PacificSky

12

ถ้าเราต้องการแสดงมุมมองประเภทต่าง ๆ ใน list-view มันก็ใช้งานได้ดีgetViewTypeCount()และgetItemViewType()ใน adapter แทนที่จะสลับมุมมองView.GONEและView.VISIBLEอาจเป็นงานที่มีราคาแพงมากgetView()ซึ่งจะมีผลต่อการเลื่อนดูรายการ

โปรดตรวจสอบสิ่งนี้เพื่อการใช้งานgetViewTypeCount()และgetItemViewType()ในอะแดปเตอร์

ลิงก์: the-use-of-getviewtypecount


การส่งคืน IGNORE_ITEM_VIEW_TYPE ใน getItemViewType () จะผ่าน 'มุมมอง' เป็น null ใน getView (ตำแหน่ง int มุมมองมุมมอง ViewGroup viewGroup) บังคับให้เริ่มต้นองค์ประกอบ UI ทั้งหมด ไม่ได้เป็นตัวบ่งชี้ประสิทธิภาพที่ไม่ดีในกรณีที่มีรูปแบบตัวยึดเราจะนำมุมมอง UI ที่มีอยู่กลับมาใช้ใหม่และเราสามารถสลับมุมมองเป็น View.GONE หรือ View.VISIBLE ตามตำแหน่ง
Namrata Bagerwal

11

ดู Outttt !!!!
ฉันต้องเผชิญกับปัญหาในการใช้งานListViewเมื่อวานนี้และมันเป็นมุมมองสองประเภทสำหรับแถวที่มีการวนกลับหลังจากที่ฉันเลื่อนมัน แม้ว่าคำตอบที่ได้รับการโหวตสูงสุดในหัวข้อนี้จะให้คำอธิบายทั่วไปที่ดี แต่ก็ไม่ได้เน้นถึงข้อมูลที่สำคัญที่สุดเพื่อหยุดข้อผิดพลาด UI ด้านบนที่ฉันได้กล่าวถึง

นี่คือคำอธิบายของฉัน:
ทั้งสองgetViewTypeCount()และgetItemViewType()กำลังถูกใช้โดยวิธีการBaseAdapterของgetViewการค้นหาชนิดของมุมมองที่ควรนำมารีไซเคิลและส่งคืน (ตามที่อธิบายไว้ในคำตอบยอดนิยมภายในชุดข้อความ) แต่ถ้าคุณไม่ใช้สองวิธีนี้อย่างเป็นธรรมชาติตามเอกสาร API ของ Android คุณอาจพบปัญหาที่ฉันกล่าวถึง

สรุปแนวทางการดำเนินงาน:
ในการดำเนินการหลายประเภทViewsสำหรับListViewแถวของเราจะต้องเป็นหลักดำเนินการgetItemViewType()และgetViewTypeCount()วิธีการ และgetItemViewType()เอกสารช่วยให้เราทราบดังต่อไปนี้:

หมายเหตุ:จำนวนเต็มจะต้องอยู่ในช่วงที่จะ 0 สามารถส่งคืนได้getViewTypeCount() - 1IGNORE_ITEM_VIEW_TYPE

ดังนั้นในตัวคุณgetItemViewType()คุณควรคืนค่าประเภทมุมมองเริ่มจาก 0 ถึงประเภทสุดท้ายเป็น (จำนวนประเภท - 1) ตัวอย่างเช่นสมมติว่าคุณมีมุมมองสามประเภทเท่านั้น ดังนั้นขึ้นอยู่กับวัตถุข้อมูลสำหรับมุมมองคุณสามารถกลับ0หรือ1หรือ2จากgetItemViewType()วิธีการเช่นดัชนีอาร์เรย์ตามศูนย์ และเมื่อคุณใช้มุมมองสามประเภทgetViewTypeCount()วิธีการของคุณจะต้องคืนค่า 3

ไม่ว่าในกรณีใดถ้าคุณคืนค่าจำนวนเต็มอื่น ๆ เช่น 1, 2, 3 หรือ 111, 222, 333 สำหรับวิธีนี้คุณอาจพบข้อผิดพลาด UI ข้างต้นซึ่งคุณเพิ่งวางโดยไม่เชื่อฟัง Android API Doc

หากคุณไม่ได้รับเบาะแสหรือไม่ยังคงแก้ปัญหาและต้องการข้อมูลเพิ่มเติมโปรดอ่านของฉันคำตอบรายละเอียดภายในนี้ StackOverflow Q & A ด้าย

อ่านAndroid Developer Docสำหรับข้อมูลเพิ่มเติมที่คุณอาจพบเบาะแสโดยตรง

หวังว่าคำตอบนี้อาจเป็นประโยชน์กับใครบางคนที่นั่นเพื่อประหยัดเวลาได้มาก !!!

ไชโย !!!


1
ขอบคุณที่กล่าวถึงIGNORE_ITEM_VIEW_TYPEฉันมีข้อบกพร่องในหนึ่งใน ListView ของฉัน ฉันใช้ ArrayAdapter เพื่อแทรกมุมมองที่ประกอบด้วย 1 ภาพและ 2 มุมมองข้อความ ฉันมีมุมมองประเภทเดียวเท่านั้น ฉันพยายามที่จะไม่แทนที่วิธี getItemViewType หรือแทนที่โดยการคืนตำแหน่งหรือจำนวนเต็มฮาร์ดโค้ด ในทุกกรณีฉันพบรายการที่ซ้ำกันในรายการของฉันโดยมีพฤติกรรมแปลก ๆ เมื่อเลื่อน (ทำซ้ำการเปลี่ยนแปลง) การกลับมาIGNORE_ITEM_VIEW_TYPEในวิธีการแก้ไขปัญหา ขอบคุณ
อเล็กซ์

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