簡體   English   中英

在Android上異步加載圖片

[英]Asynchronous image loading on Android

各位開發人員大家好:)

我為Android制作了一個非常基本的圖像提取程序,可以從我的應用程序中從Web下載和顯示位圖,其代碼為:

public class BitmapFetcher {

    private static HashMap<String, SoftReference<Bitmap>> bitmapCache = new HashMap<String, SoftReference<Bitmap>>();

    public static Bitmap fetchBitmap(String urlString) {
        SoftReference<Bitmap> cachedBitmap = bitmapCache.get(urlString);

        if (cachedBitmap != null && cachedBitmap.get() != null) {
            return cachedBitmap.get();
        }

        try {
            InputStream is = fetch(urlString);

            Bitmap bitmap = BitmapFactory.decodeStream(is);
            SoftReference<Bitmap> softReferencedBitmap = new SoftReference<Bitmap>(bitmap);
            bitmapCache.put(urlString, softReferencedBitmap);

            return bitmap;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void fetchBitmapAsync(final String urlString, final ImageView view) {
        final Handler handler = new Handler() {
            public void handleMessage(Message message) {
                AsyncImageContainer imageContainer = (AsyncImageContainer) message.obj;

                imageContainer.applyImageToView();
            }
        };

        BitmapTaskRunnable asyncImageFetcherTask = new BitmapTaskRunnable(view, urlString, handler);

        new Thread(asyncImageFetcherTask).start();
    }

    public static InputStream fetch(String urlString) throws MalformedURLException, IOException {
        Log.d("BitmapFetcher", "fetch: " + urlString);
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet request = new HttpGet(urlString);
        HttpResponse response = httpClient.execute(request);

        return response.getEntity().getContent();
    }

}

BitmapTaskRunnable.java:

public class BitmapTaskRunnable implements Runnable {

    private ImageView imageView;
    private String imageUrl;
    private Handler handler;

    public BitmapTaskRunnable() {
    }

    public BitmapTaskRunnable(ImageView imageView, String imageUrl, Handler handler) {
        setImageView(imageView);
        setImageUrl(imageUrl);
        setHandler(handler);
    }

    public void run() {
        Bitmap bitmap = BitmapFetcher.fetchBitmap(getImageUrl());

        AsyncImageContainer imageContainer = new AsyncImageContainer(getImageView(), bitmap);

        handler.sendMessage(handler.obtainMessage(0, imageContainer));
    }

    public ImageView getImageView() {
        return imageView;
    }

    public void setImageView(ImageView imageView) {
        this.imageView = imageView;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public Handler getHandler() {
        return handler;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }

}

AsyncImageContainer.java:

public class AsyncImageContainer {

    private ImageView imageView;
    private Bitmap bitmap;

    public AsyncImageContainer() {
    }

    public AsyncImageContainer(ImageView imageView, Bitmap bitmap) {
        setImageView(imageView);
        setBitmap(bitmap);
    }

    public void applyImageToView() {
        getImageView().setImageBitmap(getBitmap());
    }

    public ImageView getImageView() {
        return imageView;
    }

    public void setImageView(ImageView imageView) {
        this.imageView = imageView;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

}

正如我所說的,這是非常基本的,具有非常基本的緩存,並且不會限制正在創建的線程(已經計划很快完成)。

好吧,當我需要在ListView中加載圖像時,我目前正在經歷一種奇怪的行為,我所做的是:我有一些類可以擴展ArrayAdapter並覆蓋getView以顯示我的布局,每當我需要圖像時,我將執行以下操作:

BitmapFetcher.fetchBitmapAsync(news.getChannelAvatar(), holder.channelAvatarView);

這應該開始使BitmapFetcher啟動一個新線程,該線程將下載位圖並將消息發送到處理程序,以將圖像應用於視圖(因為只有創建視圖層次結構的線程才能對其進行修改)。

列表中第二到第n個ImageView的一切都很好,但是第一個結果總是令人發瘋,更改為已下載的圖像,直到所有圖像加載完畢並解決為止。 然后,如果我稍微拖動列表,直到第一個結果消失並返回頂部,它將顯示正確的圖像。

這確實讓我感到煩惱,因為我完成了代碼的簡單得多的版本(處理程序直接將其放置在ImageView中,處理程序直接處理了該代碼,Runnable不存在,這是一個簡單的匿名Thread對象,其中覆蓋了run() ,等),並嘗試使用此版本,以為fetchBitmapAsync丟失了對正確ImageView或類似內容的引用。

Android是否會在ListView內回收Views時發生這種情況? 如果沒有,那可能是什么原因? 我在某個地方很傻嗎?在處理此代碼幾天后,我失明了嗎? :(

感謝所有的幫助:D

對於所有懶惰的圖像加載,我都使用Prime 它甚至還提供了有關如何在ListView中使用它的示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM