Здравствуйте, коллеги-разработчики:)
Я сделал очень простой сборщик изображений для 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-го изображенийeViews в списке, но 1-й результат ВСЕГДА сходит с ума, переходя на изображения, которые были загружены до тех пор, пока все изображения не загрузятся и не установятся.Затем, если я немного перетаскиваю список, пока 1-й результат не исчезнет и не вернется к началу, он отобразит правильное изображение.
Это действительно меня беспокоит, так как я сделал гораздо более простую версию кода (тот, который обработчик обрабатывал непосредственно, помещая растровое изображение в ImageView, Runnable не существовал, это был простой анонимный объект Thread с переопределением run()
и т. д.) и пробовал эту версию, думая, что каким-то образом fetchBitmapAsync
теряет ссылку на правильныйImageView или что-то в этом роде.
Происходит ли это из-за того, что Android делает для перезарядки представлений внутри ListView?Если нет, в чем может быть причина?Я где-то глуп, и через пару дней, работая над этим кодом, я ослеп?: (
Спасибо за помощь: D