Android: sichtbare ListView-Bilder flackern beim Hinzufügen von Daten zu ArrayAdapter

8

Ich habe einen benutzerdefinierten Adapter, der ArrayAdapter erweitert. Er implementiert die Ansichtshaltermuster, um Daten (Text + Bild) von einem Webdienst anzuzeigen.

zum verzögerten Laden der Bilder Ich verwende das asynchrone Aufgabenmuster aus dem erweiterten Training auf der Android-Entwickler-Website,

Ich benutze auch disk + ram bitmap cache.

Wenn weitere Daten abgerufen werden sollen, füge ich eine Fußzeilenansicht hinzu, durch deren Anklicken zusätzliche Daten vom Webdienst abgerufen und zum Adapter hinzugefügt werden.

Das Problem ist, dass beim Hinzufügen dieser neuen Daten einige der sichtbaren Bilder sich ändern und sich sofort zurück ändern, was zu einem merkwürdigen Flackern führt.

abgesehen davon, dass alles gut funktioniert und das Scrollen reibungslos ist.

Soweit ich weiß, werden diese Bildänderungen ausgeführt, wenn die sichtbaren Ansichten aktualisiert werden, wenn neue Daten hinzugefügt werden.

Gibt es eine Möglichkeit, dieses unerwünschte Verhalten zu umgehen?

Dies ist die Klasse, die die asynchronen Tasks herunterlädt und verwaltet

%Vor%

}

das ist der Adapter:

private Klasse PlaceAdapter erweitert ArrayAdapter {         final int viewResourceId;

%Vor%

mImageViewUrls ist ein WeakHashMap<ImageView, String> , das zwischen einem ImageView und einer URL abbildet, sodass redundante asynchrone Aufgabenaufrufe reduziert werden können, indem überprüft wird, ob ImageView bereits das erforderliche Bild anzeigt. Ohne diese Implementierung findet bei allen sichtbaren Bildern bei Datenänderungen ein Flackern statt. damit passiert es nur mit einigen Bildern.

EDIT: Ich habe versucht, mögliche Ursachen dieses Problems zu beseitigen, zuerst habe ich versucht, die Cache-Implementierung vollständig zu umgehen und jedes Bitmap aus dem Netzwerk herunterladen, dann habe ich versucht, meinen Adapter mit CommonsWare Endless-Adapter zu wickeln und mit beiden habe ich das gleiche Ergebnis ..so bleibt dabei nur die ImageDownloader-Klasse und mein Adapter als mögliche Ursache .. Ich bin dabei völlig verloren.

    
Gal Ben-Haim 10.11.2012, 13:43
quelle

4 Antworten

4

Der Grund für dieses Flimmern liegt darin, dass Listeneinträge in der Listenansicht wiederverwendet werden. Wenn sie erneut verwendet werden, behalten die Bildansichten in dem Listenelement die alte Bildreferenz bei, die zuerst angezeigt wird. Später, sobald ein neues Bild heruntergeladen wurde, beginnt es zu zeigen. Dies verursacht das flackernde Verhalten. Um dieses Flimmerproblem zu vermeiden, löschen Sie immer die alte Bildreferenz aus der Bildansicht, wenn sie erneut verwendet wird.

Fügen Sie in Ihrem Fall halter.image.setImageBitmap (null); nach holder = (ViewHolder) convertView.getTag ();

hinzu

Also wird Ihre getView () Methode wie folgt aussehen:

@Override public View getView (letzte int-Position, View convertView, ViewGroup-Parent) {

%Vor%

}

    
sbajaj 22.05.2014 10:55
quelle
0

Bearbeiten: Ich hatte ähnliches Problem, die Bilder verwendeten sich schnell zu ändern. Dies geschieht, weil

getView () Methode des List-Adapters wird mehrmals aufgerufen.  Bei jedem Aufruf von getView () versuchen Sie, das Bild in der Zeile herunterzuladen und zu setzen. Zu dem Zeitpunkt, zu dem das Bild aus dem Netzwerk heruntergeladen wird, kann die Zeile in der Liste, die für dieses Bild angefordert wurde, aus dem sichtbaren Bildschirmbereich verschoben worden sein, aber der Adapter versucht, diese Zeile wiederzuverwenden, was dazu führt, dass das zuvor angeforderte Bild in dieser Zeile neu gesetzt wird (zuvor angeforderte Zeilenposition).

Versuchen Sie diesen Ansatz Setzen Sie im Adapter die angeforderte URL in der ImageView mit setTag:

%Vor%

Überprüfen Sie im Cache vor dem Laden der Bitmap, ob das rechte Bild geladen ist:

%Vor%

PS: MetaItem ist nur ein POJO, das auf imageView und die URL des Bildes verweist

    
JeeZ 21.11.2012 20:30
quelle
0

Die Lösung besteht darin, Ihr Bild nicht neu zu laden, wenn es sich nicht geändert hat.

In Ihren Adaptern getView () tun:

%Vor%

bei Erfolg (fügen Sie einen ImageLoadingListener hinzu) Sie setzen holder.lastImageUrl = Pfad, bei fehlschlagen und abbrechen setzen Sie holder.lastImageUrl auf null, damit es beim nächsten Mal neu geladen wird.

    
Frank 17.09.2014 12:47
quelle
0

Sie könnten adapter.notifyDatasetChanged() aufrufen, was listview dazu veranlasst, seine Listenelemente neu zu laden. versuche nicht adapter.notifyDatasetChanged() aufzurufen Ihre ListView sollte beim Scrollen automatisch aktualisiert werden. aber dies kann beim Scrollen ArrayIndexOutOfBounds Ausnahme verursachen.

    
Amol Desai 24.09.2015 07:13
quelle