เมธอด getView () ทำงานอย่างไรเมื่อสร้างอะแดปเตอร์แบบกำหนดเองของคุณเอง


101

คำถามของฉันคือ:

  1. LayoutInflater มีหน้าที่อะไรกันแน่?
  2. เหตุใดบทความทั้งหมดที่ฉันอ่านจึงตรวจสอบว่า convertview เป็นโมฆะหรือไม่ก่อน มันหมายความว่าอะไรเมื่อมันเป็นโมฆะและเมื่อมันไม่ใช่หมายความว่าอย่างไร
  3. พารามิเตอร์หลักที่วิธีนี้ยอมรับคืออะไร?

คำตอบ:


115

1: LayoutInflaterใช้ไฟล์ XML เลย์เอาต์ของคุณและสร้าง View-object ที่แตกต่างกันจากเนื้อหา

2: อะแดปเตอร์ถูกสร้างขึ้นเพื่อนำมุมมองมาใช้ซ้ำเมื่อมุมมองถูกเลื่อนจนมองไม่เห็นอีกต่อไปสามารถใช้กับมุมมองใหม่ที่ปรากฏขึ้น มุมมองที่ใช้ซ้ำนี้คือไฟล์convertView. หากเป็นโมฆะหมายความว่าไม่มีมุมมองรีไซเคิลและเราต้องสร้างมุมมองใหม่มิฉะนั้นเราควรใช้เพื่อหลีกเลี่ยงการสร้างใหม่

3: parentมีไว้เพื่อให้คุณสามารถขยายมุมมองของคุณให้เป็นพารามิเตอร์การจัดวางที่เหมาะสม

สิ่งเหล่านี้สามารถใช้ร่วมกันเพื่อสร้างมุมมองที่จะปรากฏในรายการของคุณได้อย่างมีประสิทธิภาพ (หรือมุมมองอื่น ๆ ที่ใช้อะแดปเตอร์):

public View getView(int position, @Nullable View convertView, ViewGroup parent){
    if (convertView == null) {
        //We must create a View:
        convertView = inflater.inflate(R.layout.my_list_item, parent, false);
    }
    //Here we can do changes to the convertView, such as set a text on a TextView 
    //or an image on an ImageView.
    return convertView;
}

สังเกตการใช้LayoutInflaterซึ่งparentสามารถใช้เป็นอาร์กิวเมนต์ได้และconvertViewจะใช้ซ้ำได้อย่างไร


5
Convertview == null มีประโยชน์เมื่อ itens ทั้งหมดของคุณเป็นไปตามเค้าโครงเดียวกัน เมื่อคุณต้องการตรวจสอบวิทยุหรือปุ่มที่เลือกเช่นและเปลี่ยนเค้าโครงตามแต่ละรายการคุณจะต้องทำการขยายใหม่หรือจะได้รับมุมมองแคช
58

ไม่จำเป็นต้องเปิดใหม่เกินไป เพียงแค่คุณต้องเขียนสวิตช์หรือบันได if-else ใน getview และขยายมุมมองตามกรณีของคุณแทนที่ public int getItemViewType (ตำแหน่ง int) และ int สาธารณะ getViewTypeCount () @sagits
Prashanth Debbadwar

หากคำสั่งมักใช้งานได้ แต่เมื่อใช้ปุ่มตัวเลือกแก้ไขข้อความและสิ่งเหล่านี้ฉันประสบปัญหาในการใช้มุมมองแคชมีคำถามบางอย่างเกี่ยวกับสิ่งนี้ในสแตกล้น
เกิด

71

getView()วิธีการในอะแดปเตอร์สำหรับมุมมองการสร้างของรายการของListView, Gallery...

  1. LayoutInflaterถูกนำมาใช้เพื่อให้ได้มุมมองวัตถุที่คุณกำหนดในรูปแบบ XML (วัตถุรากปกติLinearLayout, FrameLayoutหรือRelativeLayout)

  2. convertViewสำหรับการรีไซเคิล สมมติว่าคุณมีมุมมองรายการซึ่งแสดงได้ครั้งละ 10 รายการเท่านั้นและขณะนี้กำลังแสดงรายการ 1 -> รายการ 10 เมื่อคุณเลื่อนลงหนึ่งรายการรายการที่ 1 จะไม่อยู่นอกหน้าจอและรายการที่ 11 จะปรากฏขึ้น . ในการสร้างมุมมองสำหรับรายการ 11 จะมีการเรียกเมธอด getView () และ convertViewนี่คือมุมมองของรายการ 1 (ซึ่งไม่จำเป็นอีกต่อไป) ดังนั้นแทนที่จะสร้างมุมมองวัตถุใหม่สำหรับรายการที่ 11 (ซึ่งเป็นค่าใช้จ่าย) ทำไมไม่กลับมาใช้convertView? => เราตรวจสอบว่าconvertViewเป็นโมฆะหรือไม่ถ้า null สร้างมุมมองใหม่มิฉะนั้นจะใช้convertViewซ้ำ

  3. parentViewคือ ListView หรือ Gallery ... ซึ่งมีมุมมองของรายการที่getView()สร้างขึ้น

หมายเหตุ : คุณไม่ได้เรียกใช้เมธอดนี้โดยตรงเพียงแค่ต้องนำไปใช้เพื่อบอกมุมมองผู้ปกครองว่าจะสร้างมุมมองของรายการได้อย่างไร


2
คำอธิบายที่ยอดเยี่ยมสำหรับ parentView ไม่สามารถหาคำอธิบายที่ดีไปกว่านี้ได้ +1
Ahmed Adel Ismail

คำอธิบายสุดทึ่ง!
gabi

คำอธิบายที่ดี +1
tpk

8

คุณสามารถดูวิดีโอนี้เกี่ยวกับมุมมองรายการ จากปีที่แล้ว Google IO และยังคงเป็นรายการที่ดีที่สุดในความคิดของฉัน

http://www.youtube.com/watch?v=wDBM6wVEO70

  1. มันขยายเลย์เอาต์ (ไฟล์ xml บน res / layout / โฟลเดอร์ของคุณ) เป็น java Objects เช่น LinearLayout และมุมมองอื่น ๆ

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

  3. ช่วยให้คุณสามารถอ้างอิงมุมมองรายการของคุณจากอะแดปเตอร์


5

LayoutInflater มีหน้าที่อะไรกันแน่?

เมื่อคุณออกแบบโดยใช้ XML องค์ประกอบ UI ทั้งหมดของคุณเป็นเพียงแท็กและพารามิเตอร์ ก่อนที่คุณจะสามารถใช้องค์ประกอบ UI เหล่านี้ (เช่น TextView หรือ LinearLayout) คุณต้องสร้างวัตถุจริงที่สอดคล้องกับองค์ประกอบ xml เหล่านี้ นั่นคือสิ่งที่พองลมมีไว้สำหรับ Inflater ใช้แท็กเหล่านี้และพารามิเตอร์ที่เกี่ยวข้องเพื่อสร้างออบเจ็กต์จริงและตั้งค่าพารามิเตอร์ทั้งหมด หลังจากนี้คุณจะได้รับการอ้างอิงถึงองค์ประกอบ UI โดยใช้ findViewById ()

เหตุใดบทความทั้งหมดที่ฉันอ่านจึงตรวจสอบว่า convertview เป็นโมฆะหรือไม่ก่อน มันหมายความว่าอะไรเมื่อมันเป็นโมฆะและเมื่อมันไม่ใช่หมายความว่าอย่างไร

นี่คือสิ่งที่น่าสนใจ คุณจะเห็น getView () ถูกเรียกทุกครั้งที่รายการในรายการถูกดึงออกมา ตอนนี้ก่อนที่จะสามารถวาดรายการได้จะต้องมีการสร้าง ตอนนี้โดยทั่วไปแล้ว convertView เป็นมุมมองที่ใช้ล่าสุดในการวาดรายการ ใน getView () คุณจะขยาย xml ก่อนแล้วจึงใช้ findByViewID () เพื่อรับองค์ประกอบ UI ต่างๆของรายการ เมื่อเราตรวจสอบ (convertView == null) สิ่งที่เราทำคือตรวจสอบว่าหากมุมมองเป็นโมฆะ (สำหรับรายการแรก) จากนั้นสร้างขึ้นหรือไม่หากมีอยู่แล้วให้นำกลับมาใช้ใหม่ไม่จำเป็นต้องผ่านกระบวนการขยายอีกครั้ง . ทำให้มีประสิทธิภาพมากขึ้น

คุณต้องเจอแนวคิดของ ViewHolder ใน getView () ทำให้รายการมีประสิทธิภาพมากขึ้น สิ่งที่เราทำคือสร้างผู้ดูและจัดเก็บข้อมูลอ้างอิงถึงองค์ประกอบ UI ทั้งหมดที่เราได้รับหลังจากขยาย ด้วยวิธีนี้เราสามารถหลีกเลี่ยงการเรียก findByViewId () จำนวนมากและประหยัดเวลาได้มาก ViewHolder นี้ถูกสร้างขึ้นในเงื่อนไข (convertView == null) และถูกเก็บไว้ใน convertView โดยใช้ setTag () ในลูปอื่นเราเพิ่งได้รับมันกลับมาโดยใช้ getView () และนำมาใช้ใหม่

พารามิเตอร์หลักที่วิธีนี้ยอมรับคืออะไร?

พาเรนต์คือ ViewGroup ซึ่งในที่สุดมุมมองของคุณที่สร้างโดย getView () จะถูกแนบ ตอนนี้ในกรณีของคุณนี่คือ ListView

หวังว่านี่จะช่วยได้ :)


4
  1. โครงร่างพองขยาย / เพิ่ม XML ภายนอกในมุมมองปัจจุบันของคุณ

  2. getView () ถูกเรียกหลายครั้งรวมถึงเมื่อเลื่อน ดังนั้นถ้ามันมีมุมมองที่สูงเกินจริงแล้วเราก็ไม่อยากทำอีกเพราะการขยายเป็นกระบวนการที่มีค่าใช้จ่ายสูง .. นั่นคือเหตุผลที่เราตรวจสอบว่าโมฆะหรือไม่แล้วขยาย

  3. มุมมองหลักคือเซลล์เดียวของรายการของคุณ ..


3
ที่นี่มีการอธิบายมุมมองผู้ปกครองไม่ถูกต้อง จะเป็น ListView ไม่ใช่ ListItem
Varun Jain

2

LayoutInflaterใช้เพื่อสร้างมุมมองแบบไดนามิกของ XML สำหรับListViewไอเท็มหรือในonCreateViewแฟรกเมนต์

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

พารามิเตอร์พาเรนต์ของgetView()เมธอดให้การอ้างอิงถึงโครงร่างพาเรนต์ซึ่งมี listView สมมติว่าคุณต้องการรับ Id ของรายการใด ๆ ใน XML หลักที่คุณสามารถใช้ได้:

ViewParent nv = parent.getParent();

while (nv != null) {

    if (View.class.isInstance(nv)) {
        final View button = ((View) nv).findViewById(R.id.remove);
        if (button != null) {
            // FOUND IT!
            // do something, then break;
            button.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.d("Remove", "Remove clicked");

                    ((Button) button).setText("Hi");
                }
            });
        }
        break;
    }

 }

1

getView()วิธีการสร้างใหม่ViewหรือViewGroupสำหรับแต่ละแถวListviewหรือ Spinner คุณสามารถกำหนดสิ่งนี้ViewหรือViewGroupในLayout XMLไฟล์ในres/layoutโฟลเดอร์และสามารถให้การอ้างอิงกับAdapterคลาส Object

หากคุณมี 4 รายการใน Array ที่ส่งไปยัง Adapter getView()method จะสร้าง 4 View สำหรับ Adaper 4 แถว

คลาส LayoutInflater มี Method ขยาย () ซึ่งสร้าง View Object จากเค้าโครงทรัพยากร XML


0

คุณยังสามารถค้นหาข้อมูลที่เป็นประโยชน์เกี่ยวกับ getView ได้ที่อินเทอร์เฟซ Adapter ในไฟล์ Adapter.java มันบอกว่า;

/**
 * Get a View that displays the data at the specified position in the data set. You can either
 * create a View manually or inflate it from an XML layout file. When the View is inflated, the
 * parent View (GridView, ListView...) will apply default layout parameters unless you use
 * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
 * to specify a root view and to prevent attachment to the root.
 * 
 * @param position The position of the item within the adapter's data set of the item whose view
 *        we want.
 * @param convertView The old view to reuse, if possible. Note: You should check that this view
 *        is non-null and of an appropriate type before using. If it is not possible to convert
 *        this view to display the correct data, this method can create a new view.
 *        Heterogeneous lists can specify their number of view types, so that this View is
 *        always of the right type (see {@link #getViewTypeCount()} and
 *        {@link #getItemViewType(int)}).
 * @param parent The parent that this view will eventually be attached to
 * @return A View corresponding to the data at the specified position.
 */
View getView(int position, View convertView, ViewGroup parent);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.