ArrayIndexOutOfBoundsException con adattatore Android personalizzato per più viste in ListView


185

Sto tentando di creare un adattatore personalizzato per il mio ListView poiché ogni elemento nell'elenco può avere una vista diversa (un collegamento, un interruttore o un gruppo radio), ma quando provo a eseguire l'attività che utilizza ListView ricevo un errore e l'app si interrompe. L'applicazione è destinata alla piattaforma Android 1.6.

Il codice:

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

}

L'errore che ricevo:

    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)

So che l'applicazione sta tornando da getViewe tutto sembra in ordine.

Qualche idea su cosa potrebbe causare questo sarebbe apprezzata.

Grazie,

-Dan


Ciao Dan, sei sicuro che getCount abbia il totale di elementi da visualizzare sul tuo ListView ??? public int getCount () {return this.list.size (); }
Jorgesys,

4
Non sono riusciti a trovare un messaggio di errore meno descrittivo ...
JoeyJ

Risposte:


515

Il tipo di visualizzazione oggetto da cui stai tornando

getItemViewType()lo è >= getViewTypeCount().


24
Questo è cattivo. Non c'è modo di eseguirne il debug. Grazie mille, Romain Guy per averlo spiegato.
Yar

113
un'altra cosa è, ViewType deve iniziare da 0.
HelmiB

16
Hai ottenuto 38 voti per la risposta fino ad ora, quindi questa potrebbe essere una risposta perfetta, ma per favore aggiungi un po 'più di testo per spiegare il problema e come risolverlo ... perché non riesco ancora a capire molto da questo.
Chirag Patel,

15
Per coloro che sono sconcertati, ViewType deve restituire un indice in base zero. ad es. (0, 1, 2 ...). nel mio caso ho provato a riutilizzare R.layout ... per ViewType. immagino internamente che il valore di ViewType sia usato come indice per il riciclo del pool e non come chiave.
Samuel,

2
Grazie per aver spiegato questo errore a differenza degli sviluppatori Android che, come al solito, non potevano preoccuparsi di menzionare questo titolo essenziale nella loro documentazione.
WKS,

17

La risposta accettata è corretta Questo è quello che sto facendo per evitare il problema:

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
}

Potrebbe essere carino solo se getItemViewTypenon
dovessi

0

Il problema si presenta quando il valore getItemType è errato. Questo valore deve essere un numero intero e deve essere compreso tra 0 e getViewTypeCount () - 1.


-3

Il motivo è molto probabilmente perché il metodo getItemViewType sta restituendo valori errati! Ogni riga nella visualizzazione elenco è una vista singola. Durante lo scrooling getItemViewType raggiunge più del conteggio di View.

Cosa fare? Come evitare il problema?

Per prima cosa determinare la vista (riga) nella visualizzazione elenco che viene mostrata per prima. Durante lo scorrimento utilizzare l'equazione del modulatore

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

In questo esempio sono disponibili dieci visualizzazioni (10 righe).

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;


}

Importante

Alcuni utenti hanno menzionato un'altra domanda su StackOverflow quel metodo

public int getViewTypeCount () e public int getItemViewType (int position) correzione come Tooglebutton abilita automaticamente il controllo dello stato vero su scrooling .. questo è molto sbagliato . Se non vuoi l'enbale automatico su scrool fai

toogleButton.setChecked(false);

sul metodo di sostituzione getView.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.