ListActivity und ListAdapter – keine Geheimnisse in Android

April 22nd, 2010 by author Leave a reply »

Um eine Liste von Einträgen anzeigen zu lassen, bietet Android die Möglichkeit der ListActivity. Eine einfache ListActivity mit einer statischen Menge von Einträgen ist schnell implementiert; eine komplexe ListActivity mit eigenem ListAdapter und Performanceproblemen leider auch.


public class SimpleStaticListActivity extends ListActivity {
// ...
   private static String[] listEntries = new String[] {"1. Eintrag", "2. Eintrag", "3. Eintrag", "4. Eintrag"};
   public void onCreate() {
                super.onCreate(savedInstanceState);
                // dein Layout
		setContentView(R.layout.simpleStaticList);
                // der List-Adapter
               setListAdapter(new ArrayAdapter(this, R.id.TextView01, listEntries));
   }
}

Dies wir aber nur selten der Fall sein und auch in diesem Beispiel benutzen wir bereits einen ArrayAdapter, der die Methode getView implementiert und sich entsprechend performant um die Darstellung kümmert. In den meisten Fällen werden die Daten aus einer Datenbank stammen oder von einer anderen Datenquelle, die einen Cursor bereitstellt. Für diese Eventualität stellt Android den SimpleCursorAdapter bereit; dieser Adapter mappt eine Menge von Columns (der Datenquelle) auf eine Menge von Ids von Views.


public class SimpleCursorAdapterListActivity extends ListActivity {
// ...
   public void onCreate() {
                super.onCreate(savedInstanceState);
                // dein Layout
		setContentView(R.layout.simpleStaticList);
                // dbHelper ^= Facade zur Datenbank
               Cursor entries = dbHelper.getEntries();
               // Wichtig: Android kümmert sich um den Lifecycle des Cursors
               startManagingCursor(entries);
               SimpleCursorAdapter entryAdapter = new SimpleCursorAdapter(this, R.layout.row, entries, new String[] {"_id"}, new int[] {R.id.TextView01});
               setListAdapter(entryAdapter);
   }
}

Okay nun haben wir eine einfache Liste mit einer Menge von Einträgen, die immer gleich aussehen. Meist reicht dies schon. Will man jetzt mehr Einfluss haben, dann muss man einen eigenen ListAdapter entwickeln und die getView – Methode implementieren. Hier ist aber Vorsicht geboten. getView wird häufiger aufgerufen, als man sich vielleicht vorstellen kann. Auf der Developer Conference hat Romain Guy einen Vortrag über “Turbo-charge your UI: How to Make your Android UI Fast and Efficient” gehalten und ist genau auf diesen Punkt eingegangen. Die wichtigsten Punkte sind:

  • Erzeuge keine Objekte in der Methode, wenn es nicht wirklich notwendig ist
  • Wiederverwende das View-Element, welches als zweiter Parameter übergeben wird und setze die relevanten Werte

Ich will hier kurz einmal die schlechteste Implementierung anreißen; wenn ihr Performanceprobleme habt und eure Implementierung ähnelt dem folgenden Beispiel, dann habt ihr noch ein wenig Arbeit vor euch.


public class SlowCursorAdapter implements ListAdapter {
// ...
   public View getView(int position, View convertView, Viewgroup parent) {
      // mInflater ^= android.view.LayoutInflater
      View view = mInflater.inflate(R.layout.listItem, null);
      ((TextView) view.findItemById(R.id.textView01)).setText(position + " Eintrag");
      return view;
   }

Es wird bei diesem Code entweder zu der Fehlermeldung kommen, dass die Anwendung nicht mehr reagiert oder beim Scrollen wird die Anwendung hängen bleiben da der Garbage Collector die alten View ständig weglöschen muss. Romain Guy gibt an, dass alleine die erste Zeile 50ms Rechenzeit in Anspruch nimmt (auf seinem Google G1).

Ihr werdet sehr oft merken, dass eine Handy-CPU nicht so schnell ist, wie ein Desktop-PC (auch wenn man das eigentlich schon vorher wissen sollte) und eure “Programmlogiken” in Tasks auslagern; mein erster Berührungspunkt mit Tasks kam sehr schnell, da ich in meiner ersten App eine Gallery mit Fotos anzeigen lassen wollte und man nicht die Originalfotos einfach nehmen kann und die Thumbnails einem auch nicht bereitgestellt werden.

Es gibt also keine Geheimnisse in Android, aber man muss teilweise lange Suchen, um die richtigen Antworten zu finden, da die API – Dokumentation doch recht wortkarg ist (z.B. MediaStore.Images.Media#query).

VN:F [1.9.22_1171]
Rating: 8.0/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)
ListActivity und ListAdapter - keine Geheimnisse in Android, 8.0 out of 10 based on 3 ratings
Advertisement

3 comments

  1. Hover says:

    “da ich in meiner ersten App eine Gallery mit Fotos anzeigen lassen wollte und man nicht die Originalfotos einfach nehmen kann und die Thumbnails einem auch nicht bereitgestellt werden”

    Hi, ich wollte mal fragen wie man jetzt einen onKlickListener mit dem adapter verbinden kann. Ich komme leider nicht weiter bei dem Versuch zu registrieren was für ein Element dort angeklickt wird.
    versuch grad sowas hähnliches wie du grad beschreibst und lasse mir eine Liste mit den Bildernamen Anzeigen und möchte das Passende Bild welchen Angeklickt wird dann darstellen. Vllt. könntest du mir ja mal deinen Quelltext zur verfügung stellen natürlichnur für Private zwecke und mein Verständniss.

    Danke!

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. author says:

    Hi Hover,

    den Adapter verbindest du gar nicht mit dem onClick-Event, sondern nur deine “ListView”. Hierfür werden die Interfaces OnItemClickListener und OnItemLongClickListener bereit gestellt.

    Du musst also die Methoden der Interfaces implementieren und erhälst bei der Methode onItemClick die notwendigen Parameter, um herauszufinden, welches Objekt geklickt wurde. Zu guter letzt musst du den OnItemClickListener an der ListView setzen:

    listView.setOnItemClickListener(deinItemClickListener).

    Viel Spass.

    VN:F [1.9.22_1171]
    Rating: 2.0/5 (2 votes cast)
    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  3. Hover says:

    Hab vielen Dank!!!
    auf den OnItemClickListener bin ich ja nich gekommen 😉
    nu funzt wenigstens die Auswahl^^

    VA:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.22_1171]
    Rating: +1 (from 1 vote)

Leave a Reply