Expandable ListView dynamsch füllen

  • Antworten:6
Hauke Schrills
  • Forum-Beiträge: 67

22.02.2015, 12:38:16 via Website

Hallo Leute

Ich versuche ein Expandable ListView dynamisch zu füllen.
Jedoch haben alle child -Einträge den selben Inhalt.
Ich kann den Fehler nicht finden.
Vorlage für mein Lsitview ist von http://www.androidhive.info.
Habe es entsprechend angepasst.

Hier mein Code:

private void prepareListData() {

    Termin terminItem;   // Klasse Termin 
    listDataHeader = new ArrayList<String>();  //Headerliste 
    listDataChild = new HashMap<String, List<Termin>>(); // childliste 
    List<Termin> l_termine = new ArrayList<Termin>(); // Arraylist von Termin

    int i_month = 0;  // Monat für Header
    int i_year = 2014; // Jahr für Header
    String Zeit_von = ""; //Termin von..

    int iMdum = 0; // Dummy für Monat 
    int iYdum = 2014; // Dummy für Jahr 
    String headerName = "";
    boolean ersterEintrag = true;
    int i_count = 0;  // zählt die Header

    //T_Termin ist eine Liste von Terminen wird am Anfang deklariert sortiert nach 'Zeit von'

    for (int i = 0; i < T_Termin.size(); i++) {  


        terminItem = T_Termin.get(i);    // Termin aus Terminliste
        Zeit_von=convertDate(terminItem.getDtstart());  // Startzeit des Termins
        iMdum=Integer.parseInt(Zeit_von.substring(3,5)); // Monat des Termins
        iYdum=Integer.parseInt(Zeit_von.substring(6,10)); // Jahr des Termins

        if(iMdum!=i_month || iYdum!=i_year)   //Wenn der Monat oder das Jahr sich geändert hat
        {
            i_month=iMdum;
            i_year=iYdum;

            if(!ersterEintrag)
            {
                listDataChild.put(listDataHeader.get(i_count++), l_termine);  // gesammelte child-Termine an Liste übergeben
                l_termine.clear(); // Terminliste leeren
            }

            headerName = getMonatsname(i_month) + " " + String.valueOf(i_year);  // Headername zb Januar 2015 
            listDataHeader.add(headerName);


            ersterEintrag=false;
        }

        l_termine.add(terminItem);  // Termin in Liste übernehmen

    }

    listDataChild.put(listDataHeader.get(i_count++), l_termine); // letzen gesammelten child-Termine übergeben

    listAdapter = new ExpandableListAdapter(this, listDataHeader,listDataChild);

    // setting list adapter
    expListView.setAdapter(listAdapter);

}

Vielleicht seht Ihr den Fehler

Danke und Gruß
Hauke

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

22.02.2015, 13:11:50 via Website

Sieht ok aus, obwohl ich deine ganzen Substrings etc nicht blicke, aber egal.

Kommt ein Fehler im LogCat?
Wie sieht den dein ExpandableListAdapter aus?
Wahrscheinlich liegt es daran.

Sonst: Debugge mal den Code und prüfe, was in den beiden Array die du dem Adapter übergibst drinnesteht.
Dann finsdest du leicht heraus, ob es am Adapter liegt oder am Code oben.

LG

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Hauke Schrills
  • Forum-Beiträge: 67

22.02.2015, 14:33:17 via Website

Danke für die Antwort,

So wie es aussieht löscht

l_termine.clear(

nicht nur die Liste l_termine , sondern auch die Einträge in listDataChild
Könnte es sein ,dass ich verschiedene Listen übergeben muss, vielleicht
so etwas wie

List> a_termine = new ArrayList>();
und dann
listDataChild.put(listDataHeader.get(i_count), a_termine.get(i_count++));

??

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

22.02.2015, 14:52:01 via Website

Das ist aber komisch normalerweise:

 if(!ersterEintrag)
        {
            listDataChild.put(listDataHeader.get(i_count++), l_termine);  // gesammelte child-Termine an Liste übergeben
            l_termine.clear(); // Terminliste leeren
        }

stimmt das so und l_termine wird in listDataChild geschrieben und dann wird l_termine geleert.

Das Problem dabei ist, dass in OOP Sprachen immer nur mit Referenzen (Zeiger) gearbeitet wird.
Du übergibst deiner listDataChild Liste eine andere Liste. Um das effizient zu machen und speicher zu sparen, erstellt Java nur eine referenz, d.h. alles was du mit der Termin Liste im weitern Verlauf machst wird auch in die DataChild Liste übernommen.

Lösung:
Du brauchst eine komie der Liste welche danach nicht mehr verändert wird.

Das sieht dann so aus:

   if(!ersterEintrag)
            {
                listDataChild.put(listDataHeader.get(i_count++), l_termine.clone());  // ArrayList#clone() gibt ein neues ArrayList objekt zurück, welches mit dem Orginalen identisch ist, du aber im weiteren Verlauf nicht mehr veränderst. Somt sollte das kein porblem sein.

LG Pascal
l_termine.clear(); // Terminliste leeren
}

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Hauke Schrills
  • Forum-Beiträge: 67

22.02.2015, 15:25:47 via Website

Das wäre ein Möglichkeit aber

listDataChild = new HashMap<String, List<Termin>>(); 

erwartet ein List<> und die haben keine Methode clone
andererseits bekomme ich eine Fehlermeldung bei

listDataChild.put(listDataHeader.get(i_count++), l_termine);

The method put(String, List) in the type HashMap> is not applicable for the arguments (String, Object

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

22.02.2015, 15:47:03 via Website

Nimm stat diese List eine ArrayList, die implementiert das interface clonable und damit solltest du das dann machen können

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Hauke Schrills
  • Forum-Beiträge: 67

23.02.2015, 08:52:36 via Website

Jetzt hat es funktioniert.
noch ein cast in listDataChild.put hatte gefehlt

Danke für Deine Hilfe

Gruß Hauke

Antworten