ArrayIndexOutOfBoundsException dengan Adaptor Android khusus untuk beberapa tampilan di ListView

185

Saya mencoba membuat Adaptor khusus untuk ListView saya karena setiap item dalam daftar dapat memiliki tampilan berbeda (tautan, toggle, atau grup radio), tetapi ketika saya mencoba menjalankan Aktivitas yang menggunakan ListView saya menerima kesalahan dan aplikasi berhenti. Aplikasi ini ditargetkan untuk platform Android 1.6.

Kode:

public class MenuListAdapter extends BaseAdapter {
 private static final String LOG_KEY = MenuListAdapter.class.getSimpleName();

 protected List<MenuItem> list;
 protected Context ctx;
 protected LayoutInflater inflater;

 public MenuListAdapter(Context context, List<MenuItem> objects) {
  this.list = objects;
  this.ctx = context;
  this.inflater = (LayoutInflater)this.ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
  Log.i(LOG_KEY, "Position: " + position + "; convertView = " + convertView + "; parent=" + parent);
  MenuItem item = list.get(position);
  Log.i(LOG_KEY, "Item=" + item );

        if (convertView == null)  {
            convertView = this.inflater.inflate(item.getLayout(), null);
        }

        return convertView;
 }

 @Override
 public boolean areAllItemsEnabled() {
  return false;
 }

 @Override
 public boolean isEnabled(int position) {
  return true;
 }

 @Override
 public int getCount() {
  return this.list.size();
 }

 @Override
 public MenuItem getItem(int position) {
  return this.list.get(position);
 }

 @Override
 public long getItemId(int position) {
  return position;
 }

 @Override
 public int getItemViewType(int position) {
  Log.i(LOG_KEY, "getItemViewType: " + this.list.get(position).getLayout());
  return this.list.get(position).getLayout();
 }

 @Override
 public int getViewTypeCount() {
  Log.i(LOG_KEY, "getViewTypeCount: " + this.list.size());
  return this.list.size();
 }

}

Kesalahan yang saya terima:

    java.lang.ArrayIndexOutOfBoundsException
  at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:3523)
  at android.widget.ListView.measureHeightOfChildren(ListView.java:1158)
  at android.widget.ListView.onMeasure(ListView.java:1060)
  at android.view.View.measure(View.java:7703)

Saya tahu bahwa aplikasi kembali dari getViewdan semuanya tampak beres.

Setiap ide tentang apa yang menyebabkan ini akan dihargai.

Terima kasih,

-Dan

Dan
sumber
Hai Dan, apakah Anda yakin getCount memiliki total elemen untuk ditampilkan di ListView Anda ??? public int getCount () {return this.list.size (); }
Jorgesys
4
Mereka tidak dapat membuat pesan kesalahan yang kurang deskriptif ...
JoeyJ

Jawaban:

515

Jenis tampilan item tempat Anda kembali

getItemViewType()adalah >= getViewTypeCount().

Guy Romain
sumber
24
Yang ini jahat. Tidak ada cara untuk debug itu. Terima kasih banyak, Romain Guy telah menjelaskannya.
Yar
113
hal lain adalah, ViewType harus dimulai dari 0.
HelmiB
16
Anda mendapat 38 suara untuk jawaban sampai sekarang jadi ini mungkin jawaban yang sempurna, tapi tolong tambahkan beberapa teks untuk menjelaskan masalah dan cara mengatasinya..karena saya masih tidak bisa mengerti banyak dari ini.
Chirag Patel
15
Bagi mereka yang bingung, ViewType harus mengembalikan indeks berbasis nol. mis. (0, 1, 2 ...). dalam kasus saya, saya mencoba menggunakan kembali R.layout ... untuk tipe tampilan. Saya kira secara internal nilai ViewType sedang digunakan sebagai indeks untuk daur ulang kumpulan dan bukan sebagai kunci.
Samuel
2
Terima kasih telah menjelaskan kesalahan ini tidak seperti pengembang Android yang, seperti biasa, tidak mau repot menyebutkan titbit vital ini dalam dokumentasi mereka.
WKS
17

Jawaban yang diterima benar. Inilah yang saya lakukan untuk menghindari masalah:

public enum FoodRowType {
    ONLY_ELEM,
    FIRST_ELEM,
    MID_ELEM,
    LAST_ELEM
}

@Override
public int getViewTypeCount() {
    return FoodRowType.values().length;
}

@Override
public int getItemViewType(int position) {
    return rows.get(position).getViewType();  //returns one of the above types
}
mtbomb
sumber
Bisa jadi baik hanya jika getItemViewTypetidak kembali ke Int
dVaffection
0

Masalah muncul saat nilai getItemType salah. Nilai ini harus berupa bilangan bulat dan harus dari 0 hingga getViewTypeCount () - 1.

sunil jain
sumber
-3

Alasannya, kemungkinan besar karena metode getItemViewType mengembalikan nilai yang salah! Setiap baris dalam tampilan daftar adalah Tampilan satu. Sementara scrooling getItemViewType mencapai lebih dari hitungan View.

Apa yang harus dilakukan? Bagaimana cara menghindari masalah?

Pertama-tama tentukan tampilan (baris) dalam tampilan daftar Anda yang ditampilkan terlebih dahulu. Sementara Menggulir menggunakan persamaan moduler

    @Override
    public int getItemViewType(int position) {
        return choseType(position);//function to use modular equation
    }
    @Override
    public int getViewTypeCount() {
        return 10;
    }

Dalam contoh ini ada sepuluh tampilan (10 baris).

private  int choseType(int position){
    if(position%10==0)
        return 0;
    else if(position%10==1)
        return 1;
    else if(position%10==2)
        return 2;
    else if(position%10==3)
        return 3;
    else if(position%10==4)
        return 4;
    else if(position%10==5)
        return 5;
    else if(position%10==6)
        return 6;
    else if(position%10==7)
        return 7;
    else if(position%10==8)
        return 8;
    else
        return 9;


}

Penting

Beberapa pengguna menyebutkan pertanyaan lain tentang stackoverflow metode itu

public int getViewTypeCount () dan public int getItemViewType (posisi int) memperbaiki seperti Tooglebutton secara otomatis mengaktifkan state check true pada scrooling .. itu salah besar . Jika Anda tidak ingin enbale otomatis pada scrool lakukan saja

toogleButton.setChecked(false);

pada metode overView getView.

Beyaz
sumber