[英]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.