ArrayIndexOutOfBoundsException mit benutzerdefiniertem Android-Adapter für mehrere Ansichten in ListView

185

Ich versuche, einen benutzerdefinierten Adapter für meine ListView zu erstellen, da jedes Element in der Liste eine andere Ansicht haben kann (ein Link, ein Umschalter oder eine Funkgruppe). Wenn ich jedoch versuche, die Aktivität auszuführen, die die ListView verwendet, wird eine Fehlermeldung angezeigt Die App stoppt. Die Anwendung ist für die Android 1.6-Plattform vorgesehen.

Der Code:

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

}

Der Fehler, den ich erhalte:

    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)

Ich weiß, dass die Anwendung zurückkommt getViewund alles in Ordnung zu sein scheint.

Irgendwelche Ideen, was dies verursachen könnte, wären willkommen.

Vielen Dank,

-Dan

Dan
quelle
Hallo Dan, bist du sicher, dass getCount die Gesamtzahl der Elemente hat, die in deiner ListView angezeigt werden sollen? public int getCount () {return this.list.size (); }
Jorgesys
4
Sie konnten nicht mit einer weniger beschreibenden Fehlermeldung kommen ...
JoeyJ

Antworten:

515

Der Elementansichtstyp, von dem Sie zurückkehren

getItemViewType()ist >= getViewTypeCount().

Romain Guy
quelle
24
Dieser ist böse. Keine Möglichkeit, es zu debuggen. Vielen Dank, Romain Guy, dass du es erklärt hast.
Yar
113
Eine andere Sache ist, ViewType muss von 0 beginnen.
HelmiB
16
Sie haben bis jetzt 38 Stimmen für die Antwort erhalten, daher ist dies möglicherweise eine perfekte Antwort. Fügen Sie jedoch bitte einen weiteren Text hinzu, um das Problem zu erläutern und zu beheben. Weil ich immer noch nicht viel davon verstehen kann.
Chirag Patel
15
Für diejenigen, die ratlos sind, muss der ViewType einen auf Null basierenden Index zurückgeben. zB (0, 1, 2 ...). In meinem Fall habe ich versucht, das R.layout ... für den ViewType wiederzuverwenden. Ich denke, intern wird der Wert des ViewType als Index für den Recyclingpool und nicht als Schlüssel verwendet.
Samuel
2
Vielen Dank, dass Sie diesen Fehler im Gegensatz zu den Android-Entwicklern erklärt haben, die sich wie üblich nicht die Mühe gemacht haben, diesen wichtigen Leckerbissen in ihrer Dokumentation zu erwähnen.
WKS
17

Die akzeptierte Antwort ist richtig. Dies ist, was ich tue, um das Problem zu vermeiden:

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
quelle
Könnte nur schön sein, wenn getItemViewTypenicht int
dVaffection
0

Das Problem tritt auf, wenn der Wert für getItemType falsch ist. Dieser Wert sollte eine Ganzzahl sein und von 0 bis getViewTypeCount () - 1 reichen.

Sunil Jain
quelle
-3

Der Grund ist höchstwahrscheinlich, dass die Methode getItemViewType die falschen Werte zurückgibt! Jede Zeile in der Listenansicht ist eine Einzelansicht. Beim Scrooling erreicht getItemViewType mehr als die Anzahl von View.

Was ist zu tun? Wie vermeide ich Probleme?

Bestimmen Sie zuerst die Ansicht (Zeile) in Ihrer Listenansicht, die zuerst angezeigt wird. Verwenden Sie beim Scrollen die Moduler-Gleichung

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

In diesem Beispiel gibt es zehn Ansichten (10 Zeilen).

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;


}

Wichtig

Einige Benutzer haben in einer anderen Frage zum Stackoverflow diese Methode erwähnt

public int getViewTypeCount () und public int getItemViewType (int position) fix wie Tooglebutton automaticly Zustand Prüfung wahr auf scrooling .. ermöglichen , das ist groß falsch .Wenn Sie automatische enbale auf scrool wollen gerade nicht tun

toogleButton.setChecked(false);

auf getView überschreiben Methode.

Beyaz
quelle