So, ich habe mit jetzt solch einen Loader geschrieben und bin damit auch ganz glücklich. Schon allein deswegen weil die Bilder alle nicht immer und immer wieder zum neu zeichnen abgerufen werden.
Allerdings ergibt sich nun ein anderes Problem, denn wenn ich wie Rafael sagte das Layout nicht immer neu inflate, dann werden mir die Bilder wahelos an irgendwelchen anderen ImageViews im ListView angezeigt. Teilweise auch doppelt oder dreifach oder so das die ganze Liste voller Bilder ist (auch wenn im Web von der Stelle gar kein Bild kommt).
Als Beispiel: Ich habe eine ListView mit 10 Einträgen, wo laut XML aber nur zu 3 Einträgen Bilder hinterlegt sind. Demnach sollen auch nur zu den 3 Einträgen Bilder angezeigt werden. Hier werden die Bilder aber nun völlig wahelos überall angezeigt. Noch dazu kommt das beim scrollen sich die Bilder teilweise vertauschen und auch in andere ImageVies innerhalb des ListViews setzen bis ich irgendwann bei allen 10 Einträgen auch Bilder hab. Das soll so nicht sein.
Wenn ich jetzt wieder jedesmal das Layout neu inflate, funktioniert alles wunderbar, aber ich erhalte im Gegenzug wieder kleine Ruckler beim scrollen des ListViews.
Anbei wieder der Quellcode den ich geschrieben habe:
Mein "LazyLoader"
1public class LazyImageLoader {
2
3 private Map<String, Bitmap> bitmapMap;
4 private static LazyImageLoader llm = null;
5
6 public static LazyImageLoader getInstance() {
7 if(llm == null) {
8 llm = new LazyImageLoader();
9 }
10 return llm;
11 }
12
13 private LazyImageLoader() {
14 bitmapMap = new HashMap<String, Bitmap>();
15 }
16
17 public void clearCache() {
18 this.bitmapMap.clear();
19 }
20
21
22 public Bitmap fetchBitmap(String urlString) {
23 if (bitmapMap.containsKey(urlString)) {
24 return bitmapMap.get(urlString);
25 }
26
27 try {
28
29 Bitmap bmp = BitmapFactory.decodeStream(new URL(urlString).openStream());
30
31 if (bmp != null) {
32 bitmapMap.put(urlString, bmp);
33 } else {
34 Log.w(this.getClass().getSimpleName(), "Fehler beim Abrufen des Bildes");
35 }
36
37 return bmp;
38 } catch (MalformedURLException e) {
39 Log.e(this.getClass().getSimpleName(), "fetchBitmap failed", e);
40 return null;
41 } catch (IOException e) {
42 Log.e(this.getClass().getSimpleName(), "fetchBitmap failed", e);
43 return null;
44 }
45 }
46
47 // Diese Methode wird in diesem Falle vom Adapter aus aufgerufen
48 public void fetchScaledBitmapOnThread(String urlString, ImageView imageView, int maxWidth, int maxHeight) {
49
50 FetchingHandler handler = new FetchingHandler(imageView);
51 FetchingThread thread = new FetchingThread(urlString, handler, imageView.getContext(), maxWidth, maxHeight);
52 thread.start();
53 }
54
55 public class FetchingHandler extends Handler {
56
57 private ImageView imageView;
58
59 public FetchingHandler(ImageView imageView) {
60 this.imageView = imageView;
61 }
62
63 @Override
64 public void handleMessage(Message message) {
65 if(message.obj != null)
66 imageView.setImageBitmap((Bitmap) message.obj);
67 }
68 }
69
70 public class FetchingThread extends Thread {
71
72 private String urlString;
73 private Handler handler;
74 private Context c;
75 private int maxWidth;
76 private int maxHeight;
77
78 public FetchingThread( String urlString, Handler handler, Context c, int maxWidth, int maxHeight ) {
79 this.urlString = urlString;
80 this.handler = handler;
81 this.c = c;
82 this.maxHeight = maxHeight;
83 this.maxWidth = maxWidth;
84 }
85
86 public void run() {
87
88 Bitmap bmp = fetchBitmap( urlString );
89 if(bmp != null)
90 bmp = PictureManipulation.resizeProportionalMax( bmp, maxWidth, maxHeight, c );
91 Message message = handler.obtainMessage( 1, bmp );
92 handler.sendMessage( message );
93 }
94 }
95
96}
Hier ist meine aktuelle getView() Methode des Adapters
1@Override
2 public View getView(int position, View convertView, ViewGroup parent) {
3
4 if(convertView == null) {
5 LayoutInflater vi = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
6 convertView = vi.inflate(R.layout.getraenk_list_item, null);
7 }
8
9 ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
10 TextView textViewName = (TextView) convertView.findViewById(R.id.itemName);
11
12
13 if(textViewName != null) {
14 textViewName.setText(itemList.get(position).getName());
15 }
16 if(imageView != null) {
17 if(itemList.get(position).getImage() != null && itemList.get(position).getImage().length() > 0) {
18 String url = itemList.get(position).getImage();
19 LazyImageLoader.getInstance().fetchScaledBitmapOnThread(url, imageView, this.imageMaxWidth, this.imageMaxHeight);
20 }
21
22 }
23
24 return convertView;
25 }
In dem Moment indem ich die Methode
1LazyImageLoader.getInstance().fetchScaledBitmapOnThread(url, imageView, this.imageMaxWidth, this.imageMaxHeight);
aufrufe, und ich mit dem debugger dort mittels Breakpoint unerbreche um zu gucken ob die richtigen Werte übergeben werden, ist auch alles so wie es sein soll. Der Wert von "position" beträgt 4, der Name und das Image des Items passen beide zusammen so wie es laut der ausgelesenen XML Datei auch sein soll, nur wird es in einem falschen ImageView eingetragen. Der Name allerdings wird mit
1textViewName.setText(itemList.get(position).getName());
an der richtigen Position im ListView eingetragen.
Wisst ihr vielleicht wo hier der Fehler liegen könnte oder was ich falsch gemacht habe?
Empfohlener redaktioneller Inhalt
Mit Deiner Zustimmung wird hier ein externer Inhalt geladen.
Mit Klick auf den oben stehenden Button erklärst Du Dich damit einverstanden, dass Dir externe Inhalte angezeigt werden dürfen. Dabei können personenbezogene Daten an Drittanbieter übermittelt werden. Mehr Infos dazu findest Du in unserer Datenschutzerklärung.