English version - "Universal Image Loader. Part 3 - Usage"
Предыдущие статьи:
В прошлой статье мы проинициализировали ImageLoader конфигурацией и теперь он готов к непосредственному использованию по назначению.
Для этого он имеет 4 перегруженных метода:
Первый вариант - все просто: говорим из какого URL-а загрузить картинку и в какой ImageView отобразить. Опции отображения (DisplayImageOptions) в этом случае будут взяты из конфигурации (defaultDisplayImageOptions(...)).
Второй вариант: вот мы уже можем определить отдельные опции для конкретной задачи. Приведем сначала примерчик создания своих опций:
Третий вариант: в дополнение ко всему вы можете "прослушивать" процесс загрузки и отображения картинки с помощью интерфейса ImageLoadingListener:
Советы и рекомендации
Иходники проекта по прежнему доступны на GitHub.
Предыдущие статьи:
В прошлой статье мы проинициализировали ImageLoader конфигурацией и теперь он готов к непосредственному использованию по назначению.
Для этого он имеет 4 перегруженных метода:
void displayImage(String url, ImageView view) void displayImage(String url, ImageView view, DisplayImageOptions options) void displayImage(String url, ImageView view, ImageLoadingListener listener) void displayImage(String url, ImageView view, DisplayImageOptions options, ImageLoadingListener listener)
Первый вариант - все просто: говорим из какого URL-а загрузить картинку и в какой ImageView отобразить. Опции отображения (DisplayImageOptions) в этом случае будут взяты из конфигурации (defaultDisplayImageOptions(...)).
Второй вариант: вот мы уже можем определить отдельные опции для конкретной задачи. Приведем сначала примерчик создания своих опций:
DisplayImageOptions options = new DisplayImageOptions.Builder() .showStubImage(R.drawable.stub_image) .showImageForEmptyUrl(R.drawable.image_for_empty_url) .resetViewBeforeLoading() .cacheInMemory() .cacheOnDisc() .decodingType(ImageScaleType.EXACT) .build();Да, опять Builder. Как говорилось в первой статье, с помощью DisplayImageOptions мы можем указать:
- надо ли отображать картинку-заглушку в ImageView, пока загружается реальная картинка, и какую именно заглушку отображать;
- надо ли отображать какую-либо картинку в ImageView, если URL картинки был передан пустым (null), и какую именно картинку отображать;
- "обнулять" ли ImageView перед началом загрузки;
- надо ли кэшировать загруженную картинку в памяти;
- надо ли кэшировать загруженную картинку на файловой системе.
- декодировать изображение максимально быстро (ImageScaleType.POWER_OF_2) или максимально экономно для оперативной памяти (ImageScaleType.EXACT).
Третий вариант: в дополнение ко всему вы можете "прослушивать" процесс загрузки и отображения картинки с помощью интерфейса ImageLoadingListener:
public interface ImageLoadingListener { void onLoadingStarted(); void onLoadingFailed(); void onLoadingComplete(); void onLoadingCancelled(); }Ну а четвертый вариант - самый мощный: можете и опции определить, и "слушать" процесс.
Советы и рекомендации
- Для того, чтобы ImageLoader смог выполнить свое предназначение, ему необходимо передать корректные параметры. И речь не столько о URL картинки, сколько об ImageView. Если вы создаете объект ImageView в коде (а не с помощью LayoutInflater), то в передавайте конструктор текущий Activity, а не контекст приложения:
- Параметры maxImageWidthForMemoryCache(...) и maxImageHeightForMemoryCache(...) стоит настраивать в конфигурации только если вы хотите загружать в ImageView картинки размера, превышающего размеры экрана устройства (например для последующего увеличения). Во всех остальных случаях этого делать не нужно: эти параметры по умолчанию учитывают размеры экрана, что позволяет экономить память при работе с Bitmap'ами.
- Устанавливайте размер пула потоков в конфигурации с умом: большой размер пула (> 10) позволит работать множеству потоков одновременно, что может сильно сказаться на отзывчивости UI. Но это можно поправить установкой более низкого приоритета для потоков: чем ниже приоритет, тем отзывчивей UI во время работы ImageLoader'а, но тем долльше грузятся картинки. Отзывчивость UI крайне важна для списков (плавная прокрутка), поэтому стоит поиграться с натройкой параметров threadPoolSize(...) и threadPriority(...) для подбора оптимальной конфигурации для вашего приложения.
- Настройки memoryCacheSize(...) и memoryCache(...) перекрывают друг друга, используйте только одну из них для одного объекта конфигурации.
- Настройки discCacheSize(...), discCacheFileCount(...) и discCache(...) перекрывают друг друга, используйте только одну из них для одного объекта конфигурации.
- Если при использовании ImageLoader'а в приложении вы всегда (или почти всегда) передаете в метод displayImage(...) одни и те же опции загрузки (DisplayImageOptions), то тогда разумным решением будет задать данные опции в конфигурации ImageLoader в качестве опций по умолчанию (метод defaultDisplayImageOptions(...)). Тогда данные опции не обязательно будет каждый раз указывать при вызове displayImage(...), т.к. если в метод явно не переданы опции, то для данной задачи будут использоваться дефолтные опции.
- Большой разницы в скорости между типами декодирования POWER_OF_2 и EXACT нет, но рекомендуется использовать POWER_OF_2 для разного рода списков (где нужно отображать много картинок небольшого размера), а EXACT для галерей (когда нужно отображать картинки в больших размерах).
ImageView imageView = new ImageView(getApplicationContext()); // НЕ ПРАВИЛЬНО! ImageView imageView = new ImageView(MyActivity.this); // правильно ImageView imageView = new ImageView(getActivity()); // правильно (для Fragment'ов)
Иходники проекта по прежнему доступны на GitHub.
Насколько я понял, в новой версии убрали DecodingType.
ReplyDeleteТочнее переименовали в ImageScaleType.
DeleteFAST -> POWER_OF_2
MEMORY_SAVING -> EXACT
Вместо картинки пришёл html (или другой мусор). Это возможно отловить? В логах вижу SkImageDecoder::Factory returned null, но как отловить ошибку декодирования я не вижу.
ReplyDeleteС помощью слушателя:
DeleteimageLoader.displayImage(imageUri, imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingFailed(FailReason failReason) {
switch (failReason) {
case IO_ERROR:
// Вот сюда должен прийти callback в случае ошибки
break;
}
}
});
Не приходит callback. Ошибки при загрузке нету. Простой способ проверить -- указать в качестве адреса картинки http://ya.ru . ImageLoader пришедший html даже кеширует.
DeleteВ новой версии 1.5.2 поправил этот момент. IO_ERROR должен приходить.
DeleteКак можно сделать, чтобы на диск кешировалось постоянно, а не только когда кеш памяти переполнится?
ReplyDeleteС чего вы взяли, что на диск кэшируется только после переполнения памяти?
DeleteПо логам видно, кроме того если после загрузки изображений отключить связь и убить приложение, то не все картинки сохранятся на карточке.
DeleteВсё, я уже разобрался. Надо было .cacheOnDisk указывать перед .cacheInMemory.
Вообще-то кэширование на диске зависит только от вызванной или не вызванной .cacheOnDisk в options. Если не указано, то и кэшировать на диске не будет, даже при "переполнении памяти".
DeleteПорядок вызова опций в options не имеет значения. Как и в конфигурации.
А нормально то, что в коде так получается что строчка : .imageScaleType(ImageScaleType.POWER_OF_2)
ReplyDeleteвыглядит так, что POWER_OF_2 зачеркнутым написанно?
Это значит, что этот параметр устарел и его лучше не использовать (в будущем он будет удален). Всю инфу можно найти в Java доках, если они вам видны. В общем, замените POWER_OF_2 на IN_SAMPLE_POWER_OF_2.
DeleteThis element neither has attached source nor attached Javadoc and hence no Javadoc could be found.
DeleteА как можно увидеть javadoc?
Попробуйте использовать jar-ку, которая в Example проекте. Там в jar-ке сразу исходникик лежат с java-доками.
DeleteНе выходит. Она вообще не присоединяется к проекту - не читается(
DeleteИмя jar-ки?
Deleteuniversal-image-loader-1.7.0-with-src.jar
DeleteА как вы его присоединяете? И какая у вас IDE?
DeleteУ меня Эклипс 4.2.0
DeleteДобавляю через Add JARs... Я что-то не так делаю? =(
Надо jar-ки закидывать в папку libs в корне проекта. Из Build Path поудалять все ссылки на jar-ки, они должны автоматически присоединяться.
DeleteОч. здорово получилось, по-моему!
ReplyDeleteОгромный выбор настроек, меняющих поведение ImageLoader'a + возможность все запустить вообще без настроек.
Прикрутил подгрузку картинок к приложению буквально с первого запуска (а до этого часа полтора читал туториалы и просматривал структуру классов :)).
Все бы так читали туториалы сначала... :) Спасибо.
DeleteЗдравствуйте!
ReplyDeleteУ меня проблема со ссылками вида:
http://tonkosti.ru/images/5/54/Caretta_Bar%26Disco%2C_%D0%BE%D1%82%D0%B5%D0%BB%D1%8C_Adora_Golf_Resort_%D0%91%D0%B5%D0%BB%D0%B5%D0%BA.jpg
Мне выдается ошибка:
libjpeg error 27 from setjmp [0 0]
Могли бы вы подсказать как справиться?
Здравствуйте. Какие это у вас особенные картинки. Дело не в ссылке, а в том, что андроидовский декодер не может задекодить такую картинку. Почему - не знаю.
DeleteМне тут сказали, что CMYK формат не читается ни на каких версиях андроида =(
Deletehttp://stackoverflow.com/questions/7608507/in-android-how-to-decode-a-jpeg-in-cmyk-color-format/7634763#7634763
Hello Sergey, I've a problem with Image Loader (wich is very fine), I just want to display a local drawable from local. So I put this URL into my String array :
ReplyDeletepublic static final String[] IMAGES = new String[]{ "drawable://" + R.drawable.app_icon }
but it doesnt work and I've a null pointer exception..
Can you tell me how display drawable ?
Look here - http://stackoverflow.com/questions/14098993/how-to-use-universal-image-loader-for-loading-resources-locally
Deleteyes but I don't understand why : "drawable://" + R.drawable.app_icon, // Image from drawables doesn't work... do you??
DeleteDid you set ExtendedImageDownloader to configuration?
Deleteyes I'm doing this in UILApplication.java : ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
Delete.threadPriority(Thread.NORM_PRIORITY - 2)
.memoryCacheSize(2 * 1024 * 1024) // 2 Mb
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.imageDownloader(new ExtendedImageDownloader(getApplicationContext()))
.tasksProcessingOrder(QueueProcessingType.LIFO)
.enableLogging() // Not necessary in common
.build();
So..
...Если открыть изображение, пролистать его в любую сторону, то при повороте экрана изображение не сохраняется. А отображается повернутый рисунок, который открывался раньше, словно пролистывания и не было... Где это можно подправить?
ReplyDeleteа... понял.. У Вас в BaseActivity идет переопределение onSaveInstanceState
ReplyDeleteСкажите, а можно как либо сохранить картинку в файловый кэш?
ReplyDeleteДопустим я сделал фотку, хочу её сразу поместить в файловый кэш, можно в принципе сохранить её по пути cacheDir который я задаю при инициализаци ImageLoader-а и прогонять имя теме же NameGenerator-ом, но нет ли более простого решения.
Пока нет.
DeleteКаким образом у Вас в библиотеке обрабатывается ошибка, возникающая в случае, если в дисковом кэше закончилось место или если дисковый кэш располагался на SD-карте и карта была отключена от девайса?
ReplyDeleteЕсли не обрабатывается, тот каким образом есть возможность обработать, а лучше предупредить данные ошибки из вне?
Данные ошибки при использования дискового кэша на SD-карте приводят к тому, что картинки перестают загружаться, а хотелось бы, чтобы библиотека просто продолжала загружать картинки без использования кэша.
Случаи такие не обрабатываются (что не есть хорошо), занес их в планы.
DeleteНа данный момент, чтобы хэндлить случаи отключения SD краты, надо сделать свой кэш (можно унаследоваться от какого-нибудь существующего, и засетить его в конфиг), в котором будет метод типа setCacheDir(File dir). Далее в случае отключения карты - сетить другую папку (StorageUtil.getCacheDirectory() пойдет).
Следить за тем, не закончилось ли место на карте, тоже придется самому, и чистить кэш в этом случае.
Над решением проблемы буду думать, но скоро ли будет - не знаю.
Здравствуйте, я взял Ваш пример, что бы попробовать что и как, и тут нагрянул вопрос, как в него можно прикрутить возможность сохранения текущего изображения, по нажатию кнопки.
ReplyDeleteЕсли вы использовали кэширование на диске, то оно уже сохранено в кэше. Остается только скопировать его куда надо. Посмотрите в сторону DiscCacheUtil.
DeleteЗдраствуйте, подскажите есть ли возможность обновить изображение в кеше. скажем загрузили картинку, она попала в кеш, затем эта картинка поменялась, скажем ориентацию например поменяла. Снова пытаемся загрузить ее, но ImageLoader берет все старую картинку из кеша( как ее обновить в кеше?
ReplyDeleteЧтобы форсировать обновление картинки, надо удалить ее из кэшей сначала. Используйте MemoryCacheUtil и DiscCacheUtil для этого. А также посмотрите в сторону LimitedAgeMemoryCache и LimitedAgeDiscCache, которые через указанное время сами удаляют картинку из кэша.
DeleteУчтите, что UIL сначала смотрит в кэш в памяти, потом в дисковый кэш, и потом загружает картинку из сети, если ее не нашлось в кэшах.
Кэши конфигурятся в конфигурации, а включаются в DisplayImageOptions.
Здаствуйте, подскажите возможно ли получить изображение как BitMap, а не сразу отображать его в ImageView? Дело в том что мне нужно отобразить изображение в ImageView как Background...
ReplyDeleteImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageView, 0 /* or maxImageWidth */, 0 /* or maxImageHeight */)
DeleteImageLoader.loadImage(..., targetSize, listener)
В листенере в onLoadingComplete(...) получаете готовую битмапку.
Сергей, спасибо за библиотеку. Есть одна проблема. Не могу правильно настроить размер пула потоков. Список подлагивает. по разному пытался настроить.. но как-то без изменений
ReplyDeleteОдна настройка размера пула не спасет, если пролемы в другом. Обязательно для списков используйте переиспользование вьюх. Вопросы вы можете задавать здесь - http://stackoverflow.com/questions/tagged/universal-image-loader
DeleteViewHolder, ViewStub... Всё имеется. Если закоментировать displayImage то список не лагает.
Deleteconfig такой
new ImageLoaderConfiguration.Builder(
getApplicationContext())
.threadPoolSize(20).threadPriority(1)
.defaultDisplayImageOptions(optionsList)
.memoryCache(new LruMemoryCache(150 * 1024 * 1024)).build();
DisplayImageOptions optionsList = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.placeholder)
.showImageOnFail(R.drawable.placeholder)
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
.showImageForEmptyUri(R.drawable.placeholder).cacheInMemory()
.cacheOnDisc().build();
.threadPoolSize(20).threadPriority(1) этого нету) уже удалил
DeleteРазмер кэша в памяти - 150 метров? Это вы зря. Максимум 16.
DeleteПовторюсь - всевопросы на StackOverFlow с подробным описанием и примерами кода.
Как можно использовать несколько ImageLoaderConfiguration?
ReplyDeleteМне надо один для списков.. что бы указывать размер высоты и ширины кеша в диск.. а второй для галерей, где надо кешировать полный размер
Если только создать два инстанса ImageLoader'а. Нужно создать свой класс и унаследовать ImageLoader.
DeleteСпасибо за совет.
DeleteПривет. Почему иногда большие фотки обрезаются при загрузки?
ReplyDeleteПривет. Не знаю.
DeleteДобрый день. У меня проблемы в использовании библиотеки с маркерами в гугл-картах. Отображается предзагрузочное изображение, а чтобы увидеть финальное, надо еще раз кликнуть по маркеру.
ReplyDeleteЯ пробовала в onLoadingComplete вызывать invalidate, но не помогает =( Не подскажете что делать?
Не подскажу. Но может посмотрите ответ здесь:
Deletehttp://stackoverflow.com/questions/16144341/android-googlemap-2-update-information-dynamically-in-infowindow-with-imageview
http://stackoverflow.com/questions/15503266/dynamic-contents-in-maps-v2-infowindow
Спасибо)
DeleteСергей. Доброго времени суток) Сразу скажу, что я только начинаю писать приложения на андроиде. И у меня возник вопрос: как, прямо из приложения, можно сделать так, чтобы установить понравившуюся картинку на рабочий стол? Спасибо.
ReplyDeleteДобрый день. Я не знаю)) UIL вам в этом не поможет.
DeleteЗдравствуйте, Сергей.
ReplyDeleteНе могу понять, как грузить картинки из дискового кеша? При отсутствии интернета они загружаются оттуда сами. Мне же надо загружать их всегда из кеша, кроме первого запуска, когда они туда загрузятся.
Здравствуйте. Не могу понять суть вашего вопроса.
DeleteМне нужна команда загрузки картинки из кеша.
DeleteСейчас загружаю картинки так:
imageLoader.displayImage(imgUrls.get(i-1).get("image").toString(), imageView, options);
Дисковый кеш создается, все нормально. Когда я выключаю интернет, все загружается из кеша автоматически. Но когда есть интернет подключение, ImageLoader начинает грузить картинки из интернета. Мне нужно, чтобы он загружал их из кеша.
Суть программы у меня в том, что есть листающиеся страницы каталога. URL картникок берется из JSON. Когда я меняю ориентацию экрана при наличии интернета, ImageLoader начинает грузить картинки из интернета, что приводит в черному экрану на 1-2 сек. Без интернет соединения переворот происходит отлично, без задержек.
ImageLoader всегда грузит картинки из кэша, если они там есть.
DeleteПокажите свои display options.
ImageLoader imageLoader = ImageLoader.getInstance();
DeleteImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.discCache(new UnlimitedDiscCache(cacheDir))
.enableLogging()
.build();
imageLoader.init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.loading37)
.cacheOnDisc()
.build();
ImageView imageView = (ImageView) page.findViewById(R.id.imageView);
DeleteImageView находятся на страницах (page.xml), которые прокручиваются компонентом ViewPager.
С чего вы взяли что UIL начинает грузить картинки из интернета при повороте экрана? Из-за черного экрана? Посмотрите лучше у себя, не делаете ли вы какой-нибудь тяжелой работы на UI потоке, в onCreate() например.
DeleteДа, я был виноват. Извините за беспокойство. Надо было вчитатся в логи. Там отчетливо написано, что изображения загружены из кеша.
DeleteСейчас все исправил, работает :)
Спасибо большое за такой отличный компонент.
This comment has been removed by the author.
DeleteПодскажите пожалуйста, в чем проблема с листенером? Пробую делать вот так:
DeleteimageLoader.displayImage(imgUrls.get(i-1).get("image").toString(), imageView, options, new ImageLoadingListener(){
@Override
public void onLoadingStarted() {
// TODO Auto-generated method stub
}
@Override
public void onLoadingFailed() {
// TODO Auto-generated method stub
}
@Override
public void onLoadingComplete() {
// TODO Auto-generated method stub
}
@Override
public void onLoadingCancelled() {
// TODO Auto-generated method stub
}});
Компилятор выдает ошибку:
The method displayImage(String, ImageView, DisplayImageOptions, ImageLoadingListener) in the type ImageLoader is not applicable for the arguments (String, ImageView, DisplayImageOptions, new MainActivity.ImageLoadingListener(){})
На хабре в примере использован именно такой способ...
Сигнатуры методов уже поменялись давно, статья порядком устарела. Посмотрите в Readme на GitHub.
DeleteЗдравствуйте. В кэш какой? В памяти или на файловой системе?
ReplyDeleteПочти. Просто он еще создает ненужный для вас Bitmap. Но другого способа нет. Передавай маленький ImageSize в loadImage(), типа new ImageSize(2, 2), чтобы создавлись маленькие битмапки, не расходовали память.
ReplyDeleteДобрый день! Когда количество изображений в GridView превышает 30, и я делаю фото, вылетает OutOfMemoryError.
ReplyDeleteПодскажите, пожалуйста, из-за чего это может быть и как возможно исправить? Я добавляю в onPause imageLoader.clearMemoryCache(), но всё равно не помогает.
Добрый день. На какой версии Android?
DeleteДобрый день!
DeleteТакая же проблема, только у меня в приложении много ListView и в каждом элементе есть картинка (75х75).
Уж чего я только не пробовал... Очень быстро расходуется виртуальная память (буквально 100 метров за 10 мин работы)
Кэш в память не использую, только на диск..
В чем может быть дело? Android 2.3.6
Please answer this question -
ReplyDeletehttp://stackoverflow.com/questions/18202439/how-to-use-dynamic-drawable-instead-of-resource-in-displayimageoptions-in-univer
Answered.
DeleteПрочитал все примеры использования, так и не понял как прикрутить "лоадер" к ImageView в списке на базе SimpleAdapter'а. Обычное добавление в список делаю через
ReplyDeletem = new HashMap();
...
m.put("img", R.Drawable.img1);
data.add(0,m);
где data это ArrayList>
Чтобы заюзать ImageLoader надо по-любому перегружать getView(...). Иначе никак.
DeleteHello Sergey Tarasevich, I have this question on stack can you check it? http://stackoverflow.com/questions/18287188/detecting-the-image-size-to-be-displayed-and-use-it-by-the-lazy-loading-image Thank you.
ReplyDeleteЗдравствуйте, Сергей! Отличная библиотека у вас получилась, у меня есть пара вопросов.
ReplyDeleteКакое будет поведение при попытке загрузки gif? Вернет ли библиотека превью первый кадр?
Как загружаются большие изображения? Например длинные 800*10000. В андройдах >4.0 отрисовка идет через opengl и отображение изображения зависит от размера текстурного буфера opengl. Есть ли идеи добавить возможность разбивать загружаемые изображения на части?
И последний вопрос: Могу ли я получить путь к кэшированому файлу по ссылке?
Спасибо! :)
При попытке загрузки gif библиотека вернет первый кадр.
DeleteОтрисока больших картинок не идет через OpenGL, картинка скейлится, как и все остальные. Есть большая вероятность, что она все равно не поместиться в памяти, или по размерным параметрам невозможно будет создать Bitmap. Идеи разбивать на части нет.
Получить путь к кэшированому файлу по ссылке: DiscCacheUtil вам в помощь.
Здравствуйте Сергей!
ReplyDeleteСкажите, пожалуйста, каким образом можно получить массив загруженных картинок без их отображения? Или же как загрузить и отобразить несколько картинок в галереи?
Заранне спасибо
Я подозреваю что можно просто проверить сколько файлов в кэше лежат например, столько и загруженных картинок.
DeleteПодскажите пожалуйста, как пофиксить OutOfMemory? использую библиотеку universal-image-loader-1.8.6-with-sources
ReplyDeleteВсе мои соображения по поводу ООМ написаны в Readme на GitHub - https://github.com/nostra13/Android-Universal-Image-Loader#useful-info
DeleteБольше ничем не могу помочь.
в какой-то момент просто перестают грузится картинки.. полагаю, что это переполнение дискового кэша.. как быть? подскажите..
ReplyDeleteHow do I get the image url link in imageview? I use Universal image loader and Added ability to download.As you can see the following codes,At that moment the displayed image imageview type URL automatically, I need to print part of file_url.I need imageview shortcut.Pleas help me.
ReplyDelete// File url to download
private static String file_url = ""; <<<<<<<-----here
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Bundle bundle = getIntent().getExtras();
imageUrls = bundle.getStringArray(Extra.RESIM);
btnShowProgress = (Button) findViewById(R.id.btnProgressBar);
my_image = (ImageView) findViewById(R.id.my_image);
/**
* Show Progress bar click event
* */
btnShowProgress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// starting new Async Task
new DownloadFileFromURL().execute(file_url);
}
});
You can keep image URL in tag of ImageView:
DeleteimageView.setTag(url);
...
String url = (String) imageView.getTag();
Есть ли возможность в опции .showStubImage(R.drawable.***) задать анимацию из ресурсов?
ReplyDeleteДа.
Deleteтак а каким образом? написала в xml-файл анимацию (list-animations), указываю ее .showStubImage(R.anim.***), но ничего не показывается, картинки грузятся но до момента отображения ничего не показывается, ни анимация, ни даже хотя бы первый кадр. сама анимация рабочая, проверила на imageview.
ReplyDeleteДа, похоже сейчас надо стартовать анимацию вручную через листенер. Посмотрите здесь решение https://github.com/nostra13/Android-Universal-Image-Loader/issues/122
Deleteспасибо
DeleteЗдравствуйте. Подскажите, какие параметры нужно установить, чтобы отображать картинку максимального качества?
ReplyDeleteЗдравствуйте.
DeleteНужно отключить скалирование картинки: DisplayImageOptions.imageScaleType(ImageScaleType.NONE)
Тогда битмапка во вьюшке будет оригинального размера. Если оригинальный размер не нужен, а важно качество декодирования, то это конфигуриться через DisplayImageOptions.bitmapConfig(...). По умолчанию стоит Bitmap.Config.ARGB_8888, т.е. самое лучшее качество.
Большое спасибо.
DeleteAfter looking at the source of this: /universalimageloader/core/ImageLoaderEngine.java
ReplyDeleteprivate final AtomicBoolean paused = new AtomicBoolean(false);
.......
void resume() {
synchronized (paused) {
paused.set(false);
paused.notifyAll();
}
}
......
Stop digging further into this library.
Check it out the goal of using Atomic from concurrency package, dude.
I understand your skepticism but this variable plays double role. This is boolean var and sync object. I can use additional variable "private Object syncObject" to implement pause/resume logic.
DeleteBut I decided re-use "paused" variable and it gives the impression of incorrect usage of AtomicBoolean.
Здравствуйте! Подскажите, пожалуйста, как правильно настроить параметры в maxImageWidthForMemoryCache(...) и maxImageHeightForMemoryCache(...) для разных по размеру устройств, чтобы можно было увеличивать картинку?
ReplyDeleteУвеличивать картинку - в смысле "зумить"? В display options указать imageScaleType(ImageScaleType.NONE)
DeleteДа, к примеру, как Вконтакте.
DeleteК сожалению, не помогло это. Мои настройки такие:
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.no_photo_details)
.resetViewBeforeLoading(true)
.cacheInMemory(true)
.cacheOnDisc(true)
.imageScaleType(ImageScaleType.NONE)
.build();
File cacheDir = StorageUtils.getCacheDirectory(context);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.memoryCacheExtraOptions(480, 800)
.threadPoolSize(3)
.threadPriority(Thread.NORM_PRIORITY - 1)
.tasksProcessingOrder(QueueProcessingType.FIFO)
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache(2 * 1024 * 1024))
.discCache(new UnlimitedDiscCache(cacheDir))
.discCacheFileNameGenerator(new HashCodeFileNameGenerator())
.defaultDisplayImageOptions(options)
.build();
Hi Sergey,
ReplyDeleteFirst of all I want THANK YOU for your work with this library.
I want to browse folders from Android device to show to the user all pictures from it.
The problem is that some times folder names or file names contain space character and I get ERROR ( for example this error: java.io.FileNotFoundException: /storage/emulated/0/Pictures/Sky%20Lantern.jpg: open failed: ENOENT (No such file or directory) )
...what should I do in this situation?
Everything else is working fine ...only this problem I have it at this time. Any help?
Thanx
I found the solution ...
DeleteString uri = fileName.getUri().toString();
String decodedUri = Uri.decode(uri);
ImageLoader.getInstance().displayImage(decodedUri, holder.img);
Take care.
Сергей, спасибо большое за проделанную работу, очень полезная библиотека!
ReplyDeleteПожалуйста :)
DeleteКлассная библиотека, пользуюсь )))
ReplyDeleteЗдравствуйте. Спасибо за библиотеку. Пытаюсь добавлять фотки в кастомный ViewGroup (без адаптера): загружаются одна - три фотки, для остальных пишет "ImageView is reused". Вот куски кода:
ReplyDeleteImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
getApplicationContext())
.threadPoolSize(5)
.threadPriority(Thread.MIN_PRIORITY + 2)
.memoryCacheSize(1500000)
.denyCacheImageMultipleSizesInMemory()
.discCache(
new TotalSizeLimitedDiscCache(cachDir, 20 * 1024 * 1024))
.imageDownloader(
new CustomBaseDownloader(getApplicationContext()))
.build();
ImageLoader.getInstance().init(config);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.placeholder_scaled)
.displayer(new FadeInBitmapDisplayer(500)).build();
final ImageView icon = new ImageView(
InventoryDetailsActivity.this);
imageLoader.displayImage(url, icon, options);
layout.addView(icon);
Это как-то решается?
Нужно бы сетить лэйаут парметры вьюхе: icon.setLayoutParams(...)
DeleteИ сначала сделать layout.addView(icon);
а потом imageLoader.displayImage(url, icon, options);
Вьюхи же всегда новые создаете в цикле?
Да, вьюхи всегда новые. Вот метод для вьюхи:
ReplyDeleteprivate View getView(final String url) {
// корневой контейнер
final RelativeLayout layout = new RelativeLayout(
InventoryDetailsActivity.this);
layout.setLayoutParams(new GridView.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
layout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
MyLog.printlog("onGlobalLayout");
int layoutWidth = layout.getWidth();
int layoutHeight = layout.getHeight();
// фото объекта
final ImageView icon = new ImageView(
InventoryDetailsActivity.this);
icon.setBackgroundColor(Color.BLACK);
iconParams = new RelativeLayout.LayoutParams((int) 14
* layoutWidth / 15,
(int) layoutWidth * 14 / 20);
iconParams.setMargins(0, (int) layoutWidth / 20, 0, 0);
icon.setLayoutParams(iconParams);
icon.setScaleType(ScaleType.FIT_CENTER);
icon.setPadding(3, 3, 3, 3);
//icon.setImageResource(R.drawable.placeholder_scaled);
layout.addView(icon);
imageLoader.displayImage(url, icon, options);
// иконка delete
final ImageView iconDelete = new ImageView(
InventoryDetailsActivity.this);
deleteIconParams = new RelativeLayout.LayoutParams(
(int) layoutWidth / 5, (int) layoutWidth / 5);
deleteIconParams.setMargins(layoutWidth
- (int) layoutWidth / 5, 0, 0, 0);
iconDelete.setLayoutParams(deleteIconParams);
layout.addView(iconDelete);
iconDelete.setImageResource(R.drawable.ic_del);
// обработчик delete
iconDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int index = gridview.indexOfChild((View) v
.getParent());
String invID = String.valueOf(inventoryDetail
.getInventoryID());
String pictureID = String
.valueOf(inventoryDetail
.getResultObjectImages()
.get(index)
.getInventoryPictureID());
sendRequestToDelete(invID, pictureID, index);
}
});
layout.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
return layout;
Честно говоря, не знаю, в чем может быть проблема.
DeleteОк, спасибо за библиотеку и за ответ.
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
DeleteСпасибо за библиотеку. Понравилось. Работает отлично. Буду читать описание, как оптимально настраивать. Скажите, а как, и можно ли настроить для просмотра большой картинки из пейджера (загружая её из кэша), увеличивая её до размеров превышающие размер экрана, как это делается в браузерах или установленных галереях.
ReplyDeleteФункциональности зуминга в UIL нет. Для этого надо использовать другие библиотеки, типа PhotView. Чтобы зумить нормально, надо поставить ImageScaleType.NONE в опциях, т.о. в ImageView будут положены полнорамерные битмапы. Хранить их в кэше в памяти (memoryCache) не рекомендую.
Deleteспасибо за ответ, теперь понятно. да согласен в памяти хранить не стоит. Да мне именно зум и нужно реализовать. какие еще библиотеки оптимальные для зумирования есть?
ReplyDeletegesture-image-view, ImageViewTouch, может еще какие. Я бы в первую очередь смотрел в cторону PhotoView/.
DeleteА чем PhotoView лучше? Есть опыт использования? Или PhotoView качественнее?
ReplyDeleteЯ сейчас попробовал PhotoView вроде работает, буду разбираться дальше
Мне кажется он качественнее, его делают проверенные люди.
DeleteСпасибо! Мне вот непонятно, если подгружать полноразмерное изображение для просмотра с зумом для всех изображений не совсем хорошо. Скорее всего при просмотре через пейджер, не все же изображения будут зумировать, то наверное лучше например выводить кликом новый ImageView в новом Activity поверх пейджера, и в котором уже тогда вывести полноразмерный битмап, который будет взаимодействовать с PhotoView со всеми прелестями зумирования?
ReplyDeleteЭто уже вам решать, как сделать.
DeleteЧасто хочется услышать совет знающего человека, правильные размышления или нет, на правильном пути или понесло не в ту сторону. Может я то что писал в корне неверно, и все гораздо проще решается...
DeleteЗуминг можно сделать и в рамках пэйджера. Просто надо будет отлавливать зуминг и при увеличении отключать обработку тачей пэйджером. Т.е.pager должен игнорить приходящие в него тачи, пока зум картинки не вернется в 1. тогда юзер снова сможет листать pager, а до этого он мог скейлить и двигать саму картинку.
ReplyDeleteСпасибо, теперь понятно. Просто пока не занимался этим вопросом, не совсем все себе представлял, то тут и с чем.
DeleteЗдравствуйте!
ReplyDeleteА можно простой пример как с помощью вашей библиотеки отобразить все изображения с определенной папки на SD карте?
imageLoader.displayImage(imageUrl, imageView); - так я могу вставить только одну картинку ((
Здравствуйте. Извините, но нету времени.
DeleteСергей, ваша библиотека просто супер, спасибо большое!) Но возникла одна проблема: в вашем примере массив с URL заранее заполнен, а мне нужно пропарсить какой-либо сайт и потом уже заполнить массив ссылками на картинки. Сколько часов ломаю голову,ничего не получается...Если не трудно, помогите пожалуйста.
ReplyDeleteВ AsyncTask во время работы парсера в ArrayList заношу ссылки на картинки:
titleUrl.add("\"" + titles.absUrl(absUrl) + "\"")
Потом заношу все ссылки в массив:
IMAGES = titleUrl.toArray(new String[titleUrl.size()])
Через Intent передаю массив в другую Activity и там же его принимаю. При запуске приложения видно, что данные из массива считываются...создаётся нужное количество ImageView и TextView, но вместо загруженного изображения отображается изображение, которое должно отображаться при ошибке загрузки. Покапался в логах и увидел, что при загрузке каждого изображения выдаётся сообщение: UIL doesn't support scheme(protocol) by default [ссылка на изображение]. You should implement this support yourself (BaseImageDownloader.getStreamFromOtherSource(...))
Всего пару дней занимаюсь разработкой приложений, но психов уже накопилось немеренно...удивляюсь, как ноутбук всё еще цел :) Буду очень благодарен, если поможете!
Судя по ошибке у вас неправильные УРЛы. Похоже они начинаются на "protocol://" или что-то типа того. Проверьте в дебаге.
DeleteВ том-то и дело, что перед этой ошибкой выдаются следующие сообщения:
DeleteStart display image task ["http://4put.ru/pictures/max/843/2590221.jpg",_144x144]
Load image from network ["http://4put.ru/pictures/max/843/2590221.jpg",_144x144]
Cache image on disc ["http://4put.ru/pictures/max/843/2590221.jpg",_144x144]
Судя по этим сообщениям, УРЛы у меня правильные, да и сам проверял массив выводом в TextView, всё заполняется правильно, точно так же, как и стандартный, уже заполненный массив...единственное отличие между ними - это ссылки. Поэтому то я и завис, потому что по логике всё правильно, но на практике не работает.
Похоже у вас в УРЛы кавычки содержат, это неправильно.
DeleteВот если честно, много раз пробовал и с кавычками, и без кавычек, и так, и сяк...но сейчас оставил только titleUrl.add(titles.absUrl(absUrl)) и чудо, всё заработало,ура,наконец-то!) Я добавлял УРЛы с кавычками,т.к. видел, что в массиве они хранятся именно в таком виде и думал,что так правильно. Спасибо большое за помощь, премного благодарен!
DeleteЕдинственный косяк, это изображения почему-то снизу размытые и растянутые получаются...т.е. верхняя часть изображения нормальная, а нижняя с дефектами.
DeleteДень добрый, подскажите пожалуйста.
ReplyDeleteИспользую Ваш universal image loader, добавляю картинки после парсинга в listview. все работает чудесно и все отображается, но проблем в том, что при скроллинге (я так понимаю, при потери фокуса на list элементе) картинка сбрасывается и если быстро заскролить несколько элементов, но нужно ждать пока картинки снова появяться в imageview. Для примера, в приложении для Вконтакта, все картинки в ленте новостей кэшируется на своих местах и не переотображаются. Где можно поискать решение данного вопроса. В ваше альгоритме или вне его?
Добрый день. Вы включили кэширование?
DeleteДень добрый, подскажите пожалуйста.
ReplyDeleteИспользую Ваш universal image loader, все работает чудесно и все отображается, но только в AVD, на телефоне или планшете вылетает с ошибкой. Куда посмотреть?
В логи.
Deleteдикие извинения, это я накосячил =)
DeleteЗдравствуйте Сергей ,спасибо за библиотеку она очень хороша..
ReplyDeleteу меня ошибка вот лог
02-23 15:02:05.499: E/ImageLoader(31372): null
02-23 15:02:05.499: E/ImageLoader(31372): java.lang.OutOfMemoryError
02-23 15:02:05.499: E/ImageLoader(31372): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
02-23 15:02:05.499: E/ImageLoader(31372): at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:613)
02-23 15:02:05.499: E/ImageLoader(31372): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:589)
02-23 15:02:05.499: E/ImageLoader(31372): at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.decodeStream(BaseImageDecoder.java:158)
02-23 15:02:05.499: E/ImageLoader(31372): at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.decode(BaseImageDecoder.java:74)
02-23 15:02:05.499: E/ImageLoader(31372): at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.decodeImage(LoadAndDisplayImageTask.java:290)
02-23 15:02:05.499: E/ImageLoader(31372): at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:244)
02-23 15:02:05.499: E/ImageLoader(31372): at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:131)
02-23 15:02:05.499: E/ImageLoader(31372): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
02-23 15:02:05.499: E/ImageLoader(31372): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
02-23 15:02:05.499: E/ImageLoader(31372): at java.lang.Thread.run(Thread.java:841)
Спасибо,
Если даю картины с маленькими размерами то нормально но когда больши(hd) то это проблема..
DeleteСергей , где я могу поменять размер кеша , и связано ли проблема указоно выше с этим...
DeleteПрисоединяюсь, такая же проблема.
DeleteРазмер можно поменять в конфигурации. .memoryCacheSize()
ReplyDeleteНу а в чем причина java.lang.OutOfMemoryError ? я понимаю что заполняется кэш , но где увеличить его размер ?
DeleteЕсли OutOfMemoryError, то размер кэша наоборот стоит уменьшать. Или вообще отказаться от кэширования в памяти. Если даже это не поможет, то значит у вас где-то утечка памяти.
DeleteЗдравствуйте Сергей ,как можно реализовать ImageLoader в AsyncTask , я имею ввиду как читать с кэша в AsyncTask
ReplyDeleteЗдравствуйте, не понимаю что вы хотите.
DeleteЗдравствуйте Сергей , заполняется оперативная память (240 mb на galaxy s3 ) в чем может быт проблема ?
ReplyDeleteСпасибо
Здравствуйте. Не знаю.
DeleteЗдраствуйте Сергей! Как сделать что бы в ImageListActivity маленькие картинки загружались с отдельных ссылок, а в ImagePageActivity загружались другие ссылки (картинки)????
ReplyDeleteЗдавствуйте, понятия не имею, о чем вы.
Deleteя хочу что бы вы помогли сделать разные потоки загрузки! в ImageListActivity загружаются картинки одни, а в ImageGridActivity другие, и в ImageGalleryActivity другие!
DeleteЗдраствуйте Сергей! Как сделать что бы ImageListActivity загружались одни картинки, а в другой ImageGridActivity другие?
ReplyDeleteEnglish Version is a 404 :(
ReplyDeleteFixed. Спасибо.
DeleteДобрый день!
ReplyDeleteПри использовании опции .displayer(new RoundedBitmapDisplayer(100)), информация о масштабировании игнорируется и отображается верхний левый угол картинки, тогда как у ImageView стоит android:scaleType="centerCrop".
Подскажите, как можно отобразить центр картинки, и при этом закруглить углы?
Добрый. RoundedBitmapDisplayer не покрывает некоторые случаи, думаю, вам стоит использовать более продвинутую вариацию для скругления - читайте в доках к RoundedBitmapDisplayer.
DeleteБольшое спасибо за ответ и за такую обширную документацию :)
DeleteПодключил https://github.com/vinc3m1/RoundedImageView , всё заработало.
Здравствуйте. Есть такая проблема: фотка по одному и тому же урлу может менятся. Кеш отключать не вариант. Есть ли возможность настроить UIL для этого случая? Или что переписать для этого(например проверять хедер lastModified)?
ReplyDeleteМожете унаследовать BaseImageDownloader и там добавить проверку lastModified и если надо, то удаляйте картинку из кэшей (MemoryCacheUtil и DiscCacheUtil для этого).
DeleteИли можете использовать кэши LimitedAge***Cache, которые удаляют закэшированные картинки периодически.
Здравствуйте, столкнулся с небольшой проблемой. Подскажите пожалуйста что можно сделать. Вот лог ошибки:
ReplyDeletejava.io.FileNotFoundException: http://is431.tfs.intravision.ru/api/taskfile/3769
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:186)
at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromNetwork(BaseImageDownloader.java:120)
at com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStream(BaseImageDownloader.java:84)
at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.getImageStream(BaseImageDecoder.java:94)
at com.nostra13.universalimageloader.core.decode.BaseImageDecoder.decode(BaseImageDecoder.java:74)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.decodeImage(LoadAndDisplayImageTask.java:264)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:237)
at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:135)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Я так понимаю не может найти файл. К сожалению невозможно указать путь к фаилу (API серверной части не позволяет), по запросу сервер возвращает изображение побитово. Что нужно сделать? Заранее благодарен за ответ.
Тогда вам надо перегрузить BaseImageDownloader.getStreamFromNetwork() и реализовать там побитовую загрузку изображения.Можете загрузить все в массив байт а потом вернуть new ByteArrayInputStream(bytes).
DeleteЗдравствуйте. У меня такой вопрос : Как можно захэшировать картинку в DiskHash без моментальной погрузки в ImageView ?
ReplyDeleteЗдравствуйте. Можно воспользоваться методом loadImage(...).
DeleteЗдравствуйте, у меня такой вопрос, можно ли вернуть картинку не ImageView, а в Bitmap ?
ReplyDeleteИспользуйте loadImage(...) с колбэком onLoadingComplete().
DeleteДобрый день, искал и наконец-то нашел, суперская библиотека, спасибо разработчикам.
ReplyDeleteУ меня назрел такой вопрос с помощью showImageOnLoading(..) можно определить временную картинку, до загрузки основной, но она статична, а можно ли залепить туда анимацию какую нить,или передать список картинок для анимации, или может есть дефолтные какие методы?
Добрый. Опишите анимацию в drawable и передавайте в showImageOnLoading(...).
Deletetest
ReplyDeleteЗдравствуйте Сергей! Спасибо за UIL! При использовании RecyclerView, адаптер в незагруженых айтемах показывет картинки из других айтемов где картинка уже подгрузилась, пробовал бороться, но все никак( прошу помощи в реализации подобного адаптера.
ReplyDeleteЗдравствуйте. Покажите свои DisplayImageOptions.
Deletepublic static void initImageLoader(Context context)
Delete{
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.diskCacheFileNameGenerator(new Md5FileNameGenerator())
.diskCacheSize(50 * 1024 * 1024) // 50 Mb
.tasksProcessingOrder(QueueProcessingType.LIFO)
.defaultDisplayImageOptions(options)
.build();
ImageLoader.getInstance().init(config);
}
Инициализация в App.
Добавьте опцию resetViewBeforeLoading() в DisplayImageOptions.
DeleteСпасибо! Помогло.
DeleteThis comment has been removed by the author.
ReplyDeleteСергей,привет!
ReplyDeleteНе подскажешь,можно ли как то вытянуть "правильные" EXIF значения с изображения,посредством UIL? Спасибо!
Здравствуйте, Сергей! Спасибо Вам огромное за библиотеку. Подскажите, пожалуйста, дизайнеры попросили реализовать следующий функционал: на месте изображения, пока оно загружается, должны отображаться 5 картинок по очереди. Подобный функционал для отображения картинок при ошибке при загрузке сделал, а тут не могу понять как. Думал, что просто в onLoadingStarted реализую, но не выходит. Заранее прошу прощения, если криво описал.
ReplyDeleteЗдравствуйте, может кто подскажет как получить исходную ссылку изображения по выбранному пользователем view (из галереи всех подгруженных изображений)? Хочу реализовать функцию удаления выбранного изображения. Спасибо.
ReplyDeleteПо какой директории и с каким именем сохраняется файл при использовании метода loadImage, если используется стандартная конфигурация? Как обращаться потом к нему, чтобы этот файл достать из диска?
ReplyDeleteСпасибо за ваш великий пост.
ReplyDeleteЯ хотел бы предложить всем, чтобы проверить http://quizbucket.org/quiz/android для андроид викторины и вопросы интервью, это может быть полезно для тех, кто готовится к собеседованию