Hello开发人员:)
我为Android制作了一个非常基本的图像获取器,可以在我的应用程序中从网上下载和显示位图,代码是:
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启动一个新线程,它将下载位图并向处理程序发送消息,将图像应用于视图(因为只有创建视图层次结构的线程才能修改它)。
列表中第2到第n个ImageViews的一切都很好,但是第一个结果总是发疯,换成已经下载的图像,直到所有图像都被加载并且它已经结束。然后,如果我拖动列表一点直到第一个结果消失并返回到顶部,它将显示正确的图像。
这真是让我烦恼,因为我做了一个更简单的代码版本(处理程序处理直接将Bitmap放在ImageView中,Runnable不存在,它是一个简单的匿名Thread对象{{ 1}}覆盖等等,并尝试这个版本认为某种方式run()
正在失去对正确的ImageView或类似的东西的引用。
Android会在ListView中回收视图吗?如果没有,可能是什么原因?我在某个地方傻了吗?经过几天工作这段代码我已经失明了? :(
感谢所有帮助:D