Прокрутка ListView с использованием UniversalImageDownloader не плавная
Я использую ListView, содержащий изображения. Эти изображения загружаются из Интернета внутри адаптера. Поэтому я использую UniversalImageDownloader.
К сожалению, прокрутка ListView на некоторое время "отстает", как только я прокручиваю вниз, куда нужно загружать новый контент.
Я ожидал, что поведение прокрутки ListView будет идеально плавным, но загрузка Image, конечно, может занять больше времени, что не должно повлиять на плавность прокрутки.
Кроме того, когда я прокручиваю обратно вверх, возникают и лаги. Кажется, что изображения не кэшируются должным образом.
Может быть, мои параметры ImageLoader настроены неправильно?
Что-то не так в моем адаптере?
ListView содержит около 20-30 изображений с размерами 640x320 (около 150 КБ)
Ниже вы можете увидеть мой адаптер, а также ImageLoader. (Класс Downloader - это просто класс-оболочка для UniversalImageDownloader)
public class Downloader {
/**
* initializes the imagedownloader with a specific configuration
* I CALL THIS METHOD RIGHT AFTER APP STARTUP
* @param c
*/
public static void initialize(Context c) {
// Create global configuration and initialize ImageLoader with this configuration
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(c)
.threadPoolSize(20)
.threadPriority(Thread.NORM_PRIORITY) // default
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.memoryCacheSize(20 * 1024 * 1024)
.memoryCacheSizePercentage(15) // default
.discCacheSize(20 * 1024 * 1024)
.discCacheFileCount(100)
.discCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
.imageDecoder(new BaseImageDecoder()) // default
.build();
ImageLoader.getInstance().init(config);
}
/**
* gets the display options that are needed when displaying an image
* @return
*/
public static DisplayImageOptions getDisplayOptions() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.error)
.showImageOnFail(R.drawable.error)
.resetViewBeforeLoading(false) // default
.cacheInMemory(true) // default
.cacheOnDisc(true) // default
.build();
return options;
}
public static ImageLoader getInstance() {
return ImageLoader.getInstance();
}
}
И адаптер:
public class EventListAdapter extends ArrayAdapter<Event> {
private List<Event> mList;
private DisplayImageOptions options;
public EventListAdapter(Context context, int list_item_resource, List<Event> objects) {
super(context, list_item_resource, objects);
mList = objects;
options = Downloader.getDisplayOptions();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Event event = mList.get(position);
// A ViewHolder keeps references to children views to avoid unneccessary calls to findViewById() on each row.
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.normalevent_list_item, parent, false);
holder = new ViewHolder();;
holder.eventimage = (ImageView) convertView.findViewById(R.id.ivEventImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if (event != null) {
holder.eventimage.setImageResource(R.drawable.loading);
// Load image, decode it to Bitmap and display Bitmap in ImageView
Downloader.getInstance().displayImage(event.getImageOneURL(), holder.eventimage, options);
}
return convertView;
}
private static class ViewHolder {
ImageView eventimage;
}
}
2 ответа
У меня была такая же проблема с загрузкой изображений. Я решил это, установив delayBeforeLoading(1000) в моих DisplayImageOptions. Необходимо начать загрузку, когда пользователь перестанет бросать.
поэтому попробуйте заменить ваш метод getDisplayOptions этим
public static DisplayImageOptions getDisplayOptions() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.error)
.showImageOnFail(R.drawable.error)
.delayBeforeLoading(1000)
.resetViewBeforeLoading(false) // default
.cacheInMemory(true) // default
.cacheOnDisc(true) // default
.build();
return options;
}
Документация также рекомендует использовать этот код, чтобы избежать задержек прокрутки в виде сетки / списка
boolean pauseOnScroll = false; // or true
boolean pauseOnFling = true; // or false
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader, pauseOnScroll, pauseOnFling);
listView.setOnScrollListener(listener);
Вы можете прочитать его здесь (последний пункт списка "Полезная информация")
Таким образом, вы можете использовать один из этих методов
@ Сергей Пекар: Ты спас мне жизнь!:) Я всегда использовал UIL для ListView для небольшого количества изображений, но затем, когда счет увеличился, я всегда запаздывал при первой загрузке (при прокрутке) изображений. Так что я также попробовал задержку, и она немного помогла и другие настройки и опции UIL, но я не был счастлив. Затем я попробовал разные библиотеки загрузки изображений (Picasso, AQuery, Volley, UrlImageViewHelper, пользовательский код). Все они работали быстрее (при первой загрузке), чем UIL, но у меня не было достаточно вариантов для меня. Так что я искал последние 2 дня для решения этой проблемы запаздывания, и спасибо Богу, я наконец нашел ваш пост здесь! Решением был PauseOnScrollListener!
Что также (дополнительно к PauseOnScrollListener) немного улучшает плавность прокрутки, расширяя ImageView для остановки requestLayout следующим образом:
public class CustomImageView extends ImageView
{
public CustomImageView (Context context, AttributeSet attributeset, int int_style)
{
super(context, attributeset, int_style);
}
public CustomImageView (Context context, AttributeSet attributeset)
{
super(context, attributeset);
}
public CustomImageView (Context context)
{
super(context);
}
@Override
public void requestLayout()
{
// Do nothing here
}
}
Для получения дополнительной информации см. Этот пост:
ListView очень медленно работает при прокрутке (используя ViewHolder/ утилизацию)