Прежде чем задать этот вопрос, я искал и читал эти:
Ленивая загрузка изображений в ListView
Android - проблема с отложенной загрузкой изображений в ListView
Моя проблема в том, что у меня есть ListView
, где:
- Каждая строка содержит
ImageView
, чей
содержимое должно быть загружено из
Интернет
- Вид каждой строки перерабатывается как в
Список ApiDemo14
Что я хочу в конечном итоге:
- Загрузка изображений лениво, только когда пользователь
свитки к ним
- Загрузка изображений в разные темы для
поддерживать отзывчивость
Мой текущий подход:
- В методе адаптера
getView()
, кроме
настраивая другие дочерние представления, я запускаю
новый поток, который загружает растровое изображение из
интернет. Когда что нить загрузки
После завершения возвращается Bitmap
, который будет установлен на ImageView
(я делаю это с помощью AsyncTask
или Handler
).
- Поскольку я перерабатываю
ImageView
с, это может
будь то случай, который я сначала хочу установить
вид с Bitmap#1
, потом позже хочу
установить его на Bitmap#2
, когда пользователь
прокручивает вниз Bitmap#1
может случиться с
займет больше времени, чем Bitmap#2
для загрузки, так
может закончиться перезаписью Bitmap#2
на
вид. Я решаю это, поддерживая
WeakHashMap
, который помнит последние Bitmap
Я хочу
установить для этого вида.
Ниже приведен псевдокод для моего текущего подхода. Я пропустил другие детали, такие как кеширование, просто чтобы прояснить ситуацию.
public class ImageLoader {
// keeps track of the last Bitmap we want to set for this ImageView
private static final WeakHashMap<ImageView, AsyncTask> assignments
= new WeakHashMap<ImageView, AsyncTask>();
/** Asynchronously sets an ImageView to some Bitmap loaded from the internet */
public static void setImageAsync(final ImageView imageView, final String imageUrl) {
// cancel whatever previous task
AsyncTask oldTask = assignments.get(imageView);
if (oldTask != null) {
oldTask.cancel(true);
}
// prepare to launch a new task to load this new image
AsyncTask<String, Integer, Bitmap> newTask = new AsyncTask<String, Integer, Bitmap>() {
protected void onPreExecute() {
// set ImageView to some "loading..." image
}
protected Bitmap doInBackground(String... urls) {
return loadFromInternet(imageUrl);
}
protected void onPostExecute(Bitmap bitmap) {
// set Bitmap if successfully loaded, or an "error" image
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(R.drawable.error);
}
}
};
newTask.execute();
// mark this as the latest Bitmap we want to set for this ImageView
assignments.put(imageView, newTask);
}
/** returns (Bitmap on success | null on error) */
private Bitmap loadFromInternet(String imageUrl) {}
}
Проблема у меня все еще есть: что, если действие будет уничтожено во время загрузки некоторых изображений?
- Есть ли риск при загрузке
поток обращается к ImageView
позже, когда активность уже
уничтожены?
- Более того,
AsyncTask
имеет некоторые глобальные
пул потоков снизу, так что если долго
задачи не отменяются, когда они
не нужно больше, я могу в конечном итоге
тратить время на загрузку вещей пользователей
не вижу Мой текущий дизайн
держать эту вещь в глобальном масштабе слишком
некрасиво, и может в конечном итоге вызвать некоторые
утечки, которые выше моего
понимание. Вместо того, чтобы делать
ImageLoader
такой синглтон,
Я думаю о создании
отдельные ImageLoader
объекты для
отличается Activities
, то когда
Activity
уничтожается, все его
AsyncTask
будет отменено. Это
слишком неловко?
Во всяком случае, мне интересно, есть ли безопасный и стандартный способ сделать это в Android. Кроме того, я не знаю iPhone, но есть ли там похожая проблема, и есть ли у них стандартный способ решения этой задачи?
Большое спасибо.