| |||||||
Das Thema "Wie verhindere ich ruckeln beim Scrollen einer ListView mit ImageView-Elementen?" befindet sich unter Android App Entwicklung auf Android-Hilfe.de.
|
| | Themen-Optionen | Ansicht |
| | #1 (permalink) |
| Neuer Benutzer Modell: HTC Desire HD Registriert seit: 27.12.2010
Beiträge: 20
Abgegebene Danke: 4
Erhielt 0 Danke für 0 Beiträge
| meine App beinhaltet eine ListActivity, die aus Elementen besteht, die wiederum 3 TextViews beinhalten für Interpret, Titel und Album, sowie eine ImageView zur Darstellung eines Albumarts. Die Liste ist quasi so aufgebaut wie die Tracklist in der Standard Musik App. Die Daten werden aus MediaStore per Cursor abgefragt und der Cursor mit einem modifizierten SimpleCursorAdapter an die ListView gebunden. Hier ist der Code: Code: void setListAdapterOverride() {
String[] fromColumns = new String[] {
AudioColumns.ARTIST,
MediaColumns.TITLE,
AudioColumns.ALBUM,
AudioColumns.ALBUM_ID
};
int[] toColumns = new int[] {
R.id.tv_artist,
R.id.tv_title,
R.id.tv_album,
R.id.iv_albumArt
};
cursorAdapter = new customAdapter(getBaseContext(), R.layout.listviewitem, cursor, fromColumns, toColumns);
setListAdapter(cursorAdapter);
if (MyDebug.Log)
Log.d("Activity", "ListAdapter gesetzt");
}
class customAdapter extends SimpleCursorAdapter {
int layout;
Cursor cursor;
String[] from;
int[] to;
public customAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.layout = layout;
this.cursor = c;
this.from = from;
this.to = to;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.listviewitem, parent, false);
if (MyDebug.Log)
Log.d("Activity", "Inflate");
}
cursor.moveToPosition(position);
TextView artist = (TextView) row.findViewById(to[0]);
TextView title = (TextView) row.findViewById(to[1]);
TextView album = (TextView) row.findViewById(to[2]);
ImageView albumArt = (ImageView) row.findViewById(to[3]);
artist.setText(cursor.getString(cursor.getColumnIndex(from[0])));
title.setText(cursor.getString(cursor.getColumnIndex(from[1])));
album.setText(cursor.getString(cursor.getColumnIndex(from[2])));
Cursor albumArtCursor = contentResolver.query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART }, MediaStore.Audio.Albums._ID + "='" + cursor.getInt(cursor.getColumnIndex(from[3])) + "'", null, null);
albumArtCursor.moveToFirst();
String albumArtUri = albumArtCursor.getString(albumArtCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
if (albumArtUri == null) albumArtUri = "default";
if (!imageCache.containsKey(albumArtUri)) {
Bitmap albumArtBitmap;
if (!albumArtUri.equals("default")) {
Options opts = new Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(albumArtUri, opts);
Integer[] bitmapSize = new Integer[] { opts.outWidth, opts.outHeight };
Integer scaleFactor = 1;
while ((bitmapSize[0]/2 > 50) && (bitmapSize[1]/2 > 50)) {
scaleFactor++;
bitmapSize[0] /= 2;
bitmapSize[1] /= 2;
}
opts = new Options();
opts.inSampleSize = scaleFactor;
albumArtBitmap = BitmapFactory.decodeFile(albumArtUri, opts);
} else {
albumArtBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_mp_song_list);
}
imageCache.put(albumArtUri, albumArtBitmap);
}
albumArt.setImageBitmap(imageCache.get(albumArtUri));
return row;
}
} In einer vorherigen Version des Codes fehlte dieser imageCache nocht, d.h. das Bild wurde jedes mal aus der Datei selbst decodiert. Das machte sich vor allem dadurch bemerkbar, dass die ListView beim scrollen extrem ruckelte. Nach Hinzufügen des imageCache ruckelt die ListView zwar nicht mehr so stark wie vorher, aber ein merkliches ruckeln ist dennoch sichtbar. Wenn ich die Tracklist in der Musik App anschaue fällt mir auf, dass sie eigentlich gar nicht ruckelt. Hat jemand von euch eine Idee wie ich den Code, bzw. das ganze Vorhaben noch weiter optimieren kann? Vielen Dank
__________________ Gruß Oli - Follow me on Twitter |
| | |
| | #2 (permalink) |
| Fortgeschrittenes Mitglied Modell: Galaxy Nexus & Motorola Xoom Registriert seit: 11.05.2009
Beiträge: 315
Abgegebene Danke: 34
Erhielt 80 Danke für 41 Beiträge
|
Du benötigst wahrscheinlich einen Efficient List Adapter.
|
| | |
| Folgender Benutzer bedankt sich bei sebastian für diesen Beitrag: | ChemDroid (09.05.2011) |
| | #3 (permalink) |
| Android Guru Registriert seit: 09.05.2009
Beiträge: 2.389
Abgegebene Danke: 36
Erhielt 307 Danke für 289 Beiträge
|
evtl das laden des bildes in einen thread auslagern?
__________________ App Entwicklung Latest apps: Media Streamer BETA | DailyCash | MoneyManager ( PRO | HD ) |
| | |
| | #4 (permalink) | |
| Neuer Benutzer Modell: HTC Desire HD Registriert seit: 27.12.2010
Beiträge: 20
Abgegebene Danke: 4
Erhielt 0 Danke für 0 Beiträge
| Zitat:
Das laden des Bildes in nen externen Thread verlegen habe ich schon ausprobiert, aber leider kann nur der UI-Thread die ImageView ändern...
__________________ Gruß Oli - Follow me on Twitter | |
| | |
| | #5 (permalink) | |
| Android Experte Modell: Samsung Galaxy Nexus Registriert seit: 16.11.2009
Beiträge: 819
Abgegebene Danke: 1
Erhielt 215 Danke für 117 Beiträge
| Zitat:
Allerdings bleibt noch das Problem, dass die Item-View ggf. schon gar nicht mehr existiert oder für ein anderes Item verwendet wird bis der Bildlade-Thread fertig ist, gerade bei schnellem Scrollen. Der Bild-Cache kann sich übrigens schnell als gelungener Schuss ins Knie entpuppen, v.a. auf etwas älteren/schwächeren Geräten, bei denen der Heap pro App auf 16MB begrenz ist. Bei 'ner etwas größeren Liste ist ein OutOfMemory vorprogrammiert... | |
| | |
| | #6 (permalink) |
| Android Experte Modell: Nexus S Registriert seit: 03.08.2009
Beiträge: 542
Abgegebene Danke: 19
Erhielt 77 Danke für 50 Beiträge
|
Mort hat das ganze schon richtig erkannt. Möchte nur noch hinzufügen, dass du zu viel in deiner getView()-Methode machst. Zu viel was den UI-Thread beschäftigt. Um das richtig smooth zu bekommen, wirst du nicht drum rum kommen, das Suchen, Laden und Dekodieren des Bildes in einen Thread auszulagern und per MessageHandler den UI-Thread darüber zu informieren, dass das gewünschte Bild nun im imageCache zur Verfügung steht (als Bitmap gleich am besten). So bleibt die Liste auf Zack und die Bilder erscheinen wenn sie geladen sind (solange eben nichts oder ein statischer Platzhalter). Richtig ist aber, dass du auf jeden Fall prüfen musst, ob deine ImageView noch existent ist. Ich würde hierbei davon abraten, die ImageView in irgendeiner Form an den Cache durchzureichen. Das erzeugt nur Speicherlecks. Eleganter ist, eine eindeutige ID als Tag zu setzen und wenn das Bild geladen ist, zu überprüfen ob das Tag noch dasselbe ist. So kannst du erkennen ob du die richtige ImageView vor dir hast. Dann noch was Allgemeines zu Caches, vor Allem bei großen Daten wie Bilder - vermeide, wenn möglich, einfache HashMaps oder Arrays als Cache. Da geht dir, wie Mort schon meinte, schneller der Speicher aus als du scrollen kannst. Elegante Alternative sind Softreferences oder WeakReferences. Android hat dir bereits eine WeakHashmap gebaut, die sich prima für Caches eignet (Doku lesen nicht vergessen).
|
| | |
| Folgender Benutzer bedankt sich bei Haggy für diesen Beitrag: | ChemDroid (09.05.2011) |
| | #7 (permalink) |
| Neuer Benutzer Modell: HTC Desire HD Registriert seit: 27.12.2010
Beiträge: 20
Abgegebene Danke: 4
Erhielt 0 Danke für 0 Beiträge
|
Vielen Dank für eure Antworten ![]() Ich habe es nun mit Hilfe der LazyList aus diesem Beitrag gelöst. Der Code ist ein wenig zu lang um ihn hier zu posten, also falls sich jemand für den Code interessiert, twittert mir einfach oder schreibt mir ne Nachricht, ich melde mich dann
__________________ Gruß Oli - Follow me on Twitter |
| | |
![]() |
|
| Themen-Optionen | |
| Ansicht | |
| |
| ||||
| Thema | Autor | Forum | Antworten | Letzter Beitrag |
| SMS: Wie verhindere ich versehentliches Senden? | ALF-Berlin | Kommunikation | 14 | 06.06.2011 11:51 |
| Kontakt ruckeln beim Scrollen - aber nicht wenn man über den App Drawer geht. | soldiers | Motorola Defy Forum | 3 | 24.02.2011 17:59 |
| Wie bekomme ich daten aus einer ListView? | MilesTeg | Android App Entwicklung | 2 | 04.12.2010 19:19 |
| Ruckeln beim Scrollen in Telefonbuch | LarsD | HTC Desire Forum | 5 | 01.06.2010 09:47 |
| Starkes Ruckeln beim Kontakte scrollen | KarlArsch | HTC Hero / T-Mobile G2 Touch Forum | 10 | 05.08.2009 18:24 |