Best Practice: Daten aus Web in ListView laden?

  • Antworten:2
Gelöschter Account
  • Forum-Beiträge: 80

09.07.2011, 17:32:06 via Website

Ich weiß, es gibt so ein ähnliches Thema bereits. Ich habe auch schon verschiedene erfolgreiche Ansätze, bin aber trotzdem noch auf der Suche nach der besten Möglichkeit und habe auch konkrete Vorstellungen. Bis jetzt sieht es bei mir wie folgt aus:

Ich starte eine Suche und erhalte Antworten (in 25er Schritten als JSON) von meinem Server-Skript. Die Daten werden in einem AsyncTask geladen. Das Ergebnis zeige ich in einer Liste an. Es enthält jeweils auch URLs zu Thumbs, welche extra geladen werden müssen. Für die Performance ist es nicht gut, die Bilder direkt zu laden und anzuzeigen. Deshalb möchte ich das Laden der Bilder in einen weiteren AsyncTask auslagern. Dazu habe ich einen ThumbLoader geschrieben, welcher genau das tun soll, sobald ihm 25 Thumbs gegeben wurden. Abgesehen davon, dass das Ganze noch nicht so funktioniert wie es soll, bin ich mir nicht sicher, ob das überhaupt die beste Lösung ist.

Wie macht ihr das? Irgendwelche Ideen? Danke, schonmal.

1package com.popsike.app;
2
3import java.io.InputStream;
4import java.util.ArrayList;
5
6import android.content.Context;
7import android.graphics.drawable.Drawable;
8import android.os.AsyncTask;
9import android.widget.ImageView;
10
11public class ThumbLoader {
12 private Utils utils = new Utils();
13 private ArrayList<ThumbToLoad> thumbsToLoad = new ArrayList<ThumbToLoad>();
14
15 public ThumbLoader(Context context) {
16 //noch nicht fertig
17 }
18
19 public void displayThumb(String url, ImageView imageView) {
20 thumbsToLoad.add(new ThumbToLoad(url, imageView));
21 if (thumbsToLoad.size()>=25) new DownloadImageTask().execute(thumbsToLoad);
22 }
23
24
25 private class ThumbToLoad{
26 private String thumbUrl;
27 private ImageView thumbView;
28 public ThumbToLoad(String u, ImageView i){
29 thumbUrl=u;
30 thumbView=i;
31 }
32 }
33
34 private void setThumb(Drawable thumb, ImageView image){
35 image.setImageDrawable(thumb);
36 }
37
38
39 private class DownloadImageTask extends AsyncTask<ArrayList<ThumbToLoad>, Void, Void> {
40
41 protected Void doInBackground(ArrayList<ThumbToLoad>... thumbList) {
42
43 for (int i=0; i<thumbList.length; i++){
44 try {
45 InputStream is = utils.fetch(thumbList[0].get(i).thumbUrl);
46 setThumb(Drawable.createFromStream(is, "src"), thumbList[0].get(i).thumbView);
47
48 } catch (Exception e){
49 e.printStackTrace();
50 }
51 }
52 return null;
53 }
54 }
55}

Antworten
Gelöschter Account
  • Forum-Beiträge: 294

12.07.2011, 21:26:39 via Website

Ich hatte schon mal eine ähnliche Problemstellung. Ich habe das damals mit einem CustomArrayAdapter, einem erweiterten ImageView (um ein URL Feld erweitert) und einem DrawableCache Singleton gelöst.

Der DrawableCache wurde für jedes Bild angefragt. Der Cache hat für jedes Bild, das noch nicht in seiner Map lag, einen Thread losgejagt und dann URL und Drawable abgelegt. Die erweiterte ImageView wurde dann vom DrawableCache bezeichnet. Vorab wurde aber das URL Feld auf Gleichheit geprüft (ListView receycled Views). Für die App habe ich mir noch eine Application instanziert und im Manifest eingetragen damit ich bei knappem Speicher benachrichtigt wurde und den Cache von älteren Einträgen befreien konnte. Zusätzlich gab es noch ein Standard Drawable welches vor dem eigentlichen Image angezeigt wurde (fest im Row Layout verdrahtet).

Der CustomAdapter hat sich um das Zeichnen der Rows gekümmert. Er hat die Images vom DrawableCache angefordert. Er hatte einen ViewHolder und war ansonsten nix Besonders.

Die ListActivity hat beim Überscrollen nach unten die nächsten 25 Einträge geholt (in einem Thread) und dann dem Adapter die weiteren gegeben. Der hat diese dann an sein Array angehangen. Die ListActivity hat dann einen notifySetDataChanged() ausgelöst und die neuen 25 hingen schwupps unten an. Den Overscroll habe ich im onScoll abgefangen. Du solltest dort aber unbedingt prüfen ob Du nicht schon auf Datenbeschaffung bist ...

Die Trennung von ListActivity und Adapter habe ich noch nie ganz sauber vollzogen. Bei mir besorgt immer die Activity die Listendaten (nicht die Bilder) und missbraucht den Adapter nur fürs Zeichnen. Das könnte man noch geschickter machen ...

Es war eigentlich nicht schwierig, man benötigt nur vorab einen Überblick was man alles benötigt.

Gruß
Harald

Gelöschter Account

Antworten
Gelöschter Account
  • Forum-Beiträge: 80

13.07.2011, 00:02:38 via Website

Vielen Dank für diese wirklich sehr ausführliche Antwort!

Mein Adapter sieht ganz ähnlich aus, bis auf dass an der Stelle mit dem Bild nichts angefordert wird, sondern Quelle und View aus dem Holder dem ThumbLoader übergeben wird, der sich um den Rest kümmern soll.

Für das Nachladen der Liste wollte ich anfangs auch einen Overscroll-Mechanismus benutzen, aber habe dann einfach aus dem letzten Listenelement ein [load more]-Button gemacht. Funktioniert auch super.

Einen Cache habe ich bisweilen noch gar nicht, das sollte ich vielleicht noch tun.

Dein Beitrag hat mir auf jeden Fall erstmal sehr geholfen, ich werde versuchen demnächst was davon umzusetzen. Dann melde ich mich nochmal.

Vielen Dank.
Manuel

Antworten