2081 Stimmen

Wie man Bilder in ListView in Android verzögert lädt

Ich verwende eine ListView um einige Bilder und die mit diesen Bildern verbundenen Beschriftungen anzuzeigen. Ich beziehe die Bilder aus dem Internet. Gibt es eine Möglichkeit, Bilder langsam zu laden, so dass die Benutzeroberfläche nicht blockiert wird, während der Text angezeigt wird, und die Bilder so angezeigt werden, wie sie heruntergeladen werden?

Die Gesamtzahl der Bilder ist nicht festgelegt.

13 Stimmen

Sie können verwenden GreenDroids AsyncImageView . Einfach anrufen setUrl .

8 Stimmen

Ich habe es benutzt. Es ist eine wunderbare Umsetzung. Schlechte Nachricht, dass AsyncImageView ist ein Teil eines großen GreenDroid Projekt, das Ihre Anwendung größer machen, auch in dem Fall, alles, was Sie brauchen, ist AsyncImageView. Auch scheint, GreenDroid Projekt ist nicht seit 2011 aktualisiert.

6 Stimmen

Sie können diese Bibliothek auch einmal ausprobieren: Android-http-image-manager die meiner Meinung nach die beste Lösung für asynchrones Laden von Bildern ist.

1151voto

James A Wilson Punkte 14495

Das habe ich erstellt, um die Bilder zu speichern, die meine App derzeit anzeigt. Bitte beachten Sie, dass das hier verwendete "Log"-Objekt mein benutzerdefinierter Wrapper um die endgültige Log-Klasse in Android ist.

package com.wilson.android.library;

/*
 Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
*/
import java.io.IOException;

public class DrawableManager {
    private final Map<String, Drawable> drawableMap;

    public DrawableManager() {
        drawableMap = new HashMap<String, Drawable>();
    }

    public Drawable fetchDrawable(String urlString) {
        if (drawableMap.containsKey(urlString)) {
            return drawableMap.get(urlString);
        }

        Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
        try {
            InputStream is = fetch(urlString);
            Drawable drawable = Drawable.createFromStream(is, "src");

            if (drawable != null) {
                drawableMap.put(urlString, drawable);
                Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                        + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                        + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
            } else {
              Log.w(this.getClass().getSimpleName(), "could not get thumbnail");
            }

            return drawable;
        } catch (MalformedURLException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        } catch (IOException e) {
            Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
            return null;
        }
    }

    public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
        if (drawableMap.containsKey(urlString)) {
            imageView.setImageDrawable(drawableMap.get(urlString));
        }

        final Handler handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message message) {
                imageView.setImageDrawable((Drawable) message.obj);
            }
        };

        Thread thread = new Thread() {
            @Override
            public void run() {
                //TODO : set imageView to a "pending" image
                Drawable drawable = fetchDrawable(urlString);
                Message message = handler.obtainMessage(1, drawable);
                handler.sendMessage(message);
            }
        };
        thread.start();
    }

    private InputStream fetch(String urlString) throws MalformedURLException, IOException {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);
        return response.getEntity().getContent();
    }
}

1051voto

Fedor Punkte 43061

Ich habe ein einfaches Beispiel für eine faule Liste (zu finden auf GitHub) mit Bildern.

Grundlegende Verwendung

ImageLoader imageLoader=new ImageLoader(context); ...
imageLoader.DisplayImage(url, imageView); 

Vergessen Sie nicht, den Zusatz folgende Berechtigungen zu Ihrer AndroidManifest.xml hinzuzufügen:

 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Please

nur eine Instanz von ImageLoader zu erstellen und sie überall in Ihrem System wiederzuverwenden Anwendung wiederverwenden. Auf diese Weise wird das Zwischenspeichern von Bildern viel effizienter sein.

Es könnte für jemanden hilfreich sein. Es lädt Bilder im Hintergrund-Thread herunter. Die Bilder werden auf einer SD-Karte und im Speicher zwischengespeichert. Die Cache-Implementierung ist sehr einfach und reicht gerade für die Demo aus. Ich dekodiere Bilder mit inSampleSize, um den Speicherverbrauch zu reduzieren. Ich versuche auch, wiederverwendete Ansichten korrekt zu behandeln.

Alt text

564voto

nostra13 Punkte 12386

Ich empfehle Open-Source-Instrumente Universal Image Loader . Es basiert ursprünglich auf dem Projekt von Fedor Vlasov LazyList und wurde seither erheblich verbessert.

  • Laden von Bildern mit mehreren Threads
  • Möglichkeit, die Konfiguration von ImageLoader in weiten Bereichen anzupassen (Thread Executors, Downloader, Decoder, Speicher- und Disk-Cache, Bildanzeigeoptionen und andere)
  • Möglichkeit der Zwischenspeicherung von Bildern im Speicher und/oder im Dateisystem des Geräts (oder auf der SD-Karte)
  • Möglichkeit zum "Abhören" des Ladevorgangs
  • Möglichkeit, jeden Aufruf des Anzeigebildes mit separaten Optionen zu personalisieren
  • Widget-Unterstützung
  • Unterstützung von Android 2.0+

166voto

Thomas Ahle Punkte 29242

Multithreading für mehr Leistung ein Tutorium von Gilles Debunne.

Dies ist ein Beitrag aus dem Android Developers Blog. Der vorgeschlagene Code verwendet:

  • AsyncTasks .
  • Eine harte, begrenzte Größe, FIFO cache .
  • Eine weiche, leicht garbage collect -Zwischenspeicher.
  • A Platzhalter Drawable während Sie herunterladen.

enter image description here

118voto

TalkLittle Punkte 8643

Update: Beachten Sie, dass diese Antwort jetzt ziemlich unwirksam ist. Der Garbage Collector reagiert aggressiv auf SoftReference und WeakReference, daher ist dieser Code NICHT für neue Anwendungen geeignet. (Versuchen Sie stattdessen Bibliotheken wie Universal Image Loader in anderen Antworten vorgeschlagen).

Danke an James für den Code und an Bao-Long für den Vorschlag, SoftReference zu verwenden. Ich habe die SoftReference-Änderungen an James' Code implementiert. Leider führten SoftReferences dazu, dass meine Bilder zu schnell in den Müll wanderten. In meinem Fall ging es auch ohne SoftReference, weil meine Listengröße begrenzt ist und meine Bilder klein sind.

Es gibt eine Diskussion von vor einem Jahr über die SoftReferences auf Google Groups: Link zum Thema . Als Lösung für die zu frühe Garbage Collection schlagen sie die Möglichkeit vor, die Heap-Größe der VM mit dalvik.system.VMRuntime.setMinimumHeapSize() manuell einzustellen, was ich nicht sehr attraktiv finde.

public DrawableManager() {
    drawableMap = new HashMap<String, SoftReference<Drawable>>();
}

public Drawable fetchDrawable(String urlString) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null)
            return drawable;
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
    try {
        InputStream is = fetch(urlString);
        Drawable drawable = Drawable.createFromStream(is, "src");
        drawableRef = new SoftReference<Drawable>(drawable);
        drawableMap.put(urlString, drawableRef);
        if (Constants.LOGGING) Log.d(this.getClass().getSimpleName(), "got a thumbnail drawable: " + drawable.getBounds() + ", "
                + drawable.getIntrinsicHeight() + "," + drawable.getIntrinsicWidth() + ", "
                + drawable.getMinimumHeight() + "," + drawable.getMinimumWidth());
        return drawableRef.get();
    } catch (MalformedURLException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    } catch (IOException e) {
        if (Constants.LOGGING) Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
        return null;
    }
}

public void fetchDrawableOnThread(final String urlString, final ImageView imageView) {
    SoftReference<Drawable> drawableRef = drawableMap.get(urlString);
    if (drawableRef != null) {
        Drawable drawable = drawableRef.get();
        if (drawable != null) {
            imageView.setImageDrawable(drawableRef.get());
            return;
        }
        // Reference has expired so remove the key from drawableMap
        drawableMap.remove(urlString);
    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            imageView.setImageDrawable((Drawable) message.obj);
        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image
            Drawable drawable = fetchDrawable(urlString);
            Message message = handler.obtainMessage(1, drawable);
            handler.sendMessage(message);
        }
    };
    thread.start();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X