รีเฟรช listView ด้วยมุมมองหลายประเภทหลังจากลบ/ลบรายการ

ฉันมี ListView พร้อมอะแดปเตอร์แบบกำหนดเองที่ขยาย BaseAdapter และมีมุมมอง 2 ประเภท เมื่อฉันเรียกใช้เมธอด adapter.removeRow(position) ข้อมูลสำหรับอะแดปเตอร์ได้รับการอัปเดตอย่างถูกต้อง และรายการสะท้อนถึงสิ่งนี้ แต่ประเภทมุมมองไม่ได้รับการอัปเดตอย่างถูกต้อง อะแดปเตอร์ได้รับการสนับสนุนจาก

ArrayList<Map<String, String>> rows = new ArrayList<Map<String, String>>();

และฉันมีเซตย่อย

List<Integer> flashSet = new ArrayList<Integer>();

ซึ่งเป็นรายการตำแหน่งทั้งหมดที่เป็นของ ViewType 1 (ตรงข้ามกับประเภทมุมมองมาตรฐาน 0)

นี่คือวิธีอะแดปเตอร์ removeRow(position) ของฉัน:

    public void removeRow(int position) {
        if (getItemViewType(position) == TYPE_FLASH) {
            flashSet.remove(position);
        }
        for (int flashPosition:flashSet) {
            System.out.println(tag+"is "+flashPosition+" going to be moved?");
             if (flashPosition > position) {
                 flashPosition -= 1;
                 System.out.println(tag+"Yes! It's been moved to "+flashPosition);
             }
        }
        rows.remove(position);
        notifyDataSetChanged();
    }

นี่คือวิธี getView ของฉัน:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        FlashHolder flashHolder;
        ClipHolder clipHolder;
        int type = getItemViewType(position);
        if (convertView == null) {
            if (type == TYPE_CLIP) {
                convertView = rowInflater.inflate(R.layout.clip_note_row_layout, null);
                clipHolder = new ClipHolder();
                flashHolder = null;
                clipHolder.textView = (TextView)(convertView.findViewById(R.id.clip_text));
                convertView.setTag(clipHolder);
            } else {
                convertView = rowInflater.inflate(R.layout.flash_row_layout, null);
                clipHolder = null;
                flashHolder = new FlashHolder();
                flashHolder.front = (TextView)(convertView.findViewById(R.id.flash_text));
                flashHolder.back = (TextView)(convertView.findViewById(R.id.clip_text));
                convertView.setTag(flashHolder);
            }
        } else {
            if (type == TYPE_CLIP) {
                clipHolder = (ClipHolder)convertView.getTag();
                flashHolder = null;
            } else {
                clipHolder = null;
                flashHolder = (FlashHolder)convertView.getTag();
            }
        }
        if (type == TYPE_CLIP) {
            clipHolder.textView.setText(rows.get(position).get("clip"));
        } else {
            flashHolder.front.setText(rows.get(position).get("flash_text"));
            flashHolder.back.setText(rows.get(position).get("clip"));
        }
        return convertView;
    }

ฉันรู้ว่าฉันสามารถสร้าง adapter ใหม่ ให้อัปเดต ArrayList และโทร listView.setAdapter(adapter) ได้ แต่ดูเหมือนว่าจะเกินกำลังทั้งหมดเมื่อฉันพยายามลบหนึ่งรายการออกจากรายการที่อาจยาว ดูภาพก่อนและหลังการลบ: Before

จากนั้นฉันจะลบรายการแรก คำว่า "ซึ่ง" ซ่อนอยู่หลังรายการ "มาดูกัน" และตอนนี้รายการ "แรงบันดาลใจจาก…" ซ่อนอยู่หลังรายการว่าง 3.

หลังจาก

ข้อมูลกำลังอัปเดต แต่ประเภทข้อมูลพร็อพเพอร์ตี้กลับไม่เป็นเช่นนั้น ขอบคุณสำหรับความช่วยเหลือ!


person willlma    schedule 13.03.2013    source แหล่งที่มา
comment
+1 สำหรับรูปลักษณ์ของแอปและการอธิบายปัญหาที่ดี   -  person Nezam    schedule 13.03.2013
comment
ขอบคุณ ฉันจะแจ้งให้คุณทราบเมื่อมีการเปิดตัวหากคุณสนใจ   -  person willlma    schedule 13.03.2013
comment
คุณได้แทนที่วิธี getViewTypeCount() และ getItemViewType() ในอะแดปเตอร์ของคุณหรือไม่?   -  person M-WaJeEh    schedule 13.03.2013
comment
ใช่ ฉันเข้าใจปัญหาแล้ว ดูคำตอบของฉันด้านล่าง ความโง่เขลาอย่างแท้จริงในส่วนของฉันและฉันต้องตั้งคำถามที่นี่เพื่อให้ฉันทราบว่าฉันผิดตรงไหน   -  person willlma    schedule 13.03.2013
comment
และฉันเห็นความไม่สอดคล้องกันในวิธี { และ } ใน getView() โปรดอัปเดตคำถามของคุณหากไม่ใช่ข้อผิดพลาดในการเขียนโค้ด   -  person M-WaJeEh    schedule 13.03.2013
comment
เสร็จแล้ว ขอบคุณ ฉันแยกส่วนบางส่วนออกจากโปรแกรมแก้ไขออนไลน์ที่นี่   -  person willlma    schedule 13.03.2013


คำตอบ (3)


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

ฉันคิดอย่างไร้เดียงสาด้วยการทำเช่นนี้

    for (int flashPosition:flashSet) {
        System.out.println(tag+"is "+flashPosition+" going to be moved?");
         if (flashPosition > position) {
             flashPosition -= 1;
             System.out.println(tag+"Yes! It's been moved to "+flashPosition);
         }
    }

ฉันกำลังเปลี่ยนค่าจริงที่เก็บไว้ใน List<Integer> flashSet = new ArrayList<Integer>();

ที่จริงแล้ว ฉันต้องทำสิ่งต่อไปนี้แทน:

for (int flashPosition:flashSet) {
    System.out.println(tag+"is "+flashPosition+" going to be moved?");
     if (flashPosition > position) {
         flashSet.remove((Object)flashPosition);
         flashPosition -= 1;
         flashSet.add(flashPosition);
         System.out.println(tag+"Yes! It's been moved to "+flashPosition);
     }
}
person willlma    schedule 13.03.2013
comment
จะดีกว่าไหมที่จะมี ArrayList<MyListData> MyListData เป็นคลาสนามธรรมและมีตัวแปร int type; ตอนนี้คุณเพียงแค่ต้องมีการใช้งานที่เป็นรูปธรรมที่แตกต่างกัน ด้วยวิธีนี้ คุณสามารถมี View ประเภทได้มากเท่าที่คุณต้องการใน ListView ของคุณ โดยไม่ต้องจัดการกลไกที่ซับซ้อนและช้าในการรักษาดัชนี เช่น. ใน getItemViewType() ของคุณ ฉันเดาว่าคุณต้องใช้วิธี List.contains() ในขณะที่วิธีการข้างต้นคุณสามารถโทร return rows.get(position).type ได้ - person M-WaJeEh; 13.03.2013
comment
ใช่แล้ว ฉันใช้ List.contains() ฉันเห็นสิ่งที่คุณหมายถึง มันเป็นความคิดที่ดี. คุณคิดว่ามันจะเสนอการปรับปรุงประสิทธิภาพหรือคุณแค่คิดว่ามันหรูหรามากขึ้น ฉันจะใช้มันหากฉันต้องการประเภทมุมมองที่สาม ขอบคุณ. - person willlma; 13.03.2013
comment
วิธีการ contains() ใช้เวลา O(n) ในการค้นหารายการ getIteViewType() ถูกเรียกหลายครั้งเมื่อผู้ใช้เลื่อนดู ListView และทุกครั้งที่ contains() วิธีการวนซ้ำ flasSet ของคุณซึ่งใช้ทรัพยากรมากกว่าในความคิดของฉัน นั่นคือสิ่งที่ฉันกำลังพูด เป็นการดีกว่าที่จะเขียนโค้ดแบบยืดหยุ่นในครั้งแรก แทนที่จะกลับมาและเปลี่ยนโค้ดทั้งหมดเพียงเพราะคุณต้องการเพิ่มส่วนหัวหรือบรรทัดแฟนซีในบางจุดใน ListView ของคุณ :) - person M-WaJeEh; 13.03.2013
comment
นอกจากนี้ เมื่อใช้วิธีการนี้ คุณจะมีประเภทข้อมูลที่แตกต่างกันโดยสิ้นเชิงสำหรับแต่ละแถวของ ListView ได้เช่นกัน ไม่ใช่แค่ Strings แถวหนึ่งอาจมี Bitmap ขนาดเล็ก ในขณะที่แถวอื่นๆ เป็นการรวมกันของ boolean และ Strings เป็นต้น - person M-WaJeEh; 13.03.2013
comment
จุดที่ถ่ายแล้ว กำลังดำเนินการอยู่. ขอบคุณ. - person willlma; 13.03.2013

ลองสิ่งนี้ หลังจากลบหรือเพิ่มรายการแล้ว คุณต้องเรียกการรีเฟรชอะแดปเตอร์

Youradapter.notifyDataSetChanged();
person MuraliGanesan    schedule 13.03.2013

ใช้ yourlistview.invalidateViews()

แทน

notifyDataSetChanged();

มันได้ผลสำหรับฉัน

person Poovizhirajan N    schedule 13.03.2013
comment
น่าเสียดายที่ฉันได้รับผลลัพธ์เดียวกัน - person willlma; 13.03.2013