Segarkan listView dengan beberapa tipe tampilan setelah menghapus/menghapus item

Saya memiliki ListView dengan adaptor khusus yang memperluas BaseAdapter dan memiliki 2 tipe tampilan. Saat saya menjalankan metode adapter.removeRow(position) saya, data untuk adaptor diperbarui dengan benar, dan daftarnya mencerminkan hal ini, tetapi tipe tampilan tidak diperbarui dengan benar. Adaptor didukung oleh

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

dan saya memiliki subset

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

yang merupakan daftar semua posisi ViewType 1 (sebagai lawan dari tipe tampilan standar 0).

Ini adalah metode adaptor removeRow(position) saya:

    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();
    }

Inilah metode getView saya:

@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;
    }

Saya tahu bahwa saya dapat membuat adapter baru, memberinya ArrayList yang diperbarui dan memanggil listView.setAdapter(adapter) tetapi ini tampaknya berlebihan ketika saya hanya mencoba menghapus satu item dari daftar yang mungkin panjang. Lihat foto sebelum dan sesudah dihapus: Sebelum

Lalu saya menghapus item pertama. Kata "yang" tersembunyi di balik item "Ayo kita tonton" dan sekarang item "terinspirasi oleh..." tersembunyi di balik item kosong 3.

Setelah

Jadi, data sedang diperbarui, tipe tampilan tidak. Terima kasih untuk bantuannya!


person willlma    schedule 13.03.2013    source sumber
comment
Memberi +1 untuk tampilan dan nuansa aplikasi serta penjelasan yang baik tentang masalahnya   -  person Nezam    schedule 13.03.2013
comment
Terima kasih. Saya akan memberi tahu Anda kapan dirilis jika Anda tertarik.   -  person willlma    schedule 13.03.2013
comment
Sudahkah Anda mengganti metode getViewTypeCount() dan getItemViewType() di adaptor Anda?   -  person M-WaJeEh    schedule 13.03.2013
comment
Ya, saya sudah menemukan masalahnya. Lihat jawaban saya di bawah ini. Benar-benar kebodohan saya dan perlu mengajukan pertanyaan di sini agar saya bisa mencari tahu di mana kesalahan saya.   -  person willlma    schedule 13.03.2013
comment
Dan saya dapat melihat ketidakkonsistenan dalam metode { dan } dalam getView() Anda. Harap perbarui pertanyaan Anda jika itu bukan kesalahan pengkodean.   -  person M-WaJeEh    schedule 13.03.2013
comment
Sudah terimakasih. Saya menghapus beberapa klausa di editor online di sini.   -  person willlma    schedule 13.03.2013


Jawaban (3)


Saya menemukan jawabannya. Ini tidak akan berguna bagi siapa pun karena saya tidak berharap orang lain melakukan kesalahan yang sama.

Saya secara naif memikirkan hal itu dengan melakukan ini

    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);
         }
    }

Saya mengubah nilai sebenarnya yang disimpan di List<Integer> flashSet = new ArrayList<Integer>();

Sebenarnya, saya perlu melakukan hal berikut:

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
Bukankah lebih mudah memiliki ArrayList<MyListData>. MyListData menjadi kelas abstrak dan memiliki variabel int type;. Sekarang Anda hanya memerlukan implementasi konkret yang berbeda. Dengan cara ini Anda dapat memiliki tipe View sebanyak yang Anda inginkan di ListView Anda, tanpa harus mengelola mekanisme yang rumit dan lambat untuk mempertahankan indeks. Misalnya. di getItemViewType() Anda, saya kira Anda mengandalkan metode List.contains() sedangkan dalam pendekatan di atas Anda cukup memanggil return rows.get(position).type. - person M-WaJeEh; 13.03.2013
comment
Ya, saya menggunakan List.contains(). Saya mengerti apa yang kamu maksud. Itu ide yang bagus. Apakah menurut Anda ini akan menawarkan peningkatan kinerja atau menurut Anda lebih elegan. Saya akan menerapkannya jika saya memerlukan tipe tampilan ketiga. Terima kasih. - person willlma; 13.03.2013
comment
Metode contains() membutuhkan O(n) waktu untuk menemukan item. getIteViewType() dipanggil berkali-kali ketika pengguna menelusuri ListView dan setiap kali metode contains() mengulangi flasSet Anda yang menghabiskan lebih banyak sumber daya, menurut pendapat saya. Itulah yang saya katakan. Lebih baik menulis kode fleksibel pertama kali daripada kembali dan mengubah seluruh kode hanya karena Anda ingin menambahkan header atau baris mewah di beberapa tempat di ListView :) - person M-WaJeEh; 13.03.2013
comment
Juga dengan menggunakan pendekatan ini Anda juga dapat memiliki tipe data yang sangat berbeda untuk setiap baris ListView Anda, bukan hanya Strings. Satu baris dapat berisi Bitmap kecil sementara baris lainnya merupakan kombinasi dari boolean dan Strings dll. - person M-WaJeEh; 13.03.2013
comment
Poin diambil. Menerapkan sekarang. Terima kasih. - person willlma; 13.03.2013

Coba ini, Setelah menghapus atau menambahkan item, Anda perlu memanggil penyegaran adaptor.

Youradapter.notifyDataSetChanged();
person MuraliGanesan    schedule 13.03.2013

gunakan yourlistview.invalidateViews()

alih-alih

notifyDataSetChanged();

itu berhasil untuk saya.

person Poovizhirajan N    schedule 13.03.2013
comment
Sayangnya, saya mendapatkan hasil yang sama. - person willlma; 13.03.2013