March 11, 2012

#5 - Universal Image Loader. Часть 2 - Конфигурация [RU+EN]

English version - "Universal Image Loader. Part 2 - Configuration"

Предыдущая статья: "Universal Image Loader. Part 1 - Введение"

    Все манипуляции проходят посредством класса ImageLoader. Это singletone, поэтому чтобы получить единственный экземпляр класса надо вызвать метод getInstance(). Перед использованием ImageLoader'а по назначению (для отображения картинок), необходимо проинициализировать его конфигурацией - ImageLoaderConfiguration, с помощью метода init(...). Ну а дальше можно со спокойной душой юзать все вариации метода displayImage(...).

    В общем, самый простой вариант использования ImageLoader'a (с конфигурацией по умолчанию) представлен ниже:
ImageView imageView = ... // вьюха, где будет отображать картинку
String imageUrl = ... // URL картинки (н-р: "http://site.com/image.png", "file:///mnt/sdcard/img/image.jpg")

ImageLoader imageLoader = ImageLoader.getInstance(); // Получили экземпляр
imageLoader.init(ImageLoaderConfiguration.createDefault(context)); // Проинициализировали конфигом по умолчанию
imageLoader.displayImage(imageUrl, imageView); // Запустили асинхронный показ картинки
   
    А теперь рассмотрим полный функционал.

    Как вы уже поняли, сначала ImageLoader надо проинициализировать с помощью объекта конфигурации. Т.к. ImageLoader - синглтон, то инициализировать его нужно один раз за запуск приложения. Я бы рекомендовал делать это в перегруженном Application.onCreate(). Повторная инициализация уже проинициализированного ImageLoader'а не будет иметь никакого эффекта.
    Значит, создаем конфигурацию, а это объект класса ImageLoaderConfiguration. Создаем с помощью Builder'а:
File cacheDir = StorageUtils.getCacheDirectory(context, "UniversalImageLoader/Cache");

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
            .memoryCacheExtraOptions(480, 800) // width, height
            .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75) // width, height, compress format, quality
            .threadPoolSize(5)
            .threadPriority(Thread.MIN_PRIORITY + 2)
            .denyCacheImageMultipleSizesInMemory()
            .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // 2 Mb
            .discCache(new UnlimitedDiscCache(cacheDir))
            .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
            .imageDownloader(new BaseImageDownloader(5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)
            .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
            .enableLogging()
            .build();
    Рассмотрим каждую настройку:
  •  memoryCacheExtraOptions() используется при декодировании изображений в объекты Bitmap. Чтобы не хранить в памяти полноразмерную картинку, она уменьшается до размера, определяемых из значений параметров ImageView, куда грузится картинка: maxWidth и maxHeight (в первую очередь), layout_width и layout_height (во вторую очередь). Если эти параметры не определены (значения fill_parent и wrap_content считаются неопределенными), то тогда берутся размеры, заданные параметрами из данного memoryCacheExtraOptions() ;
    • Значения по умолчанию - размеры экрана аппарата
  •  discCacheExtraOptions() задает параметры для хранения картинок на "дисковом кэше". По умолчанию на дисковом кэше хранятся полноразмерные картинки. С помощью данной настройки можно задать максимальный размер для хранимых картинок, а также формат сжатия и качество (для JPEG).
  •  threadPoolSize(int) задает размер пула потоков. Каждое задание на загрузку и отображение картинки выполняется в отдельном потоке, а те потоки, в которых происходит загрузка изображений из сети, попадают в пул. Т.о. размер пула определяет количество потоков, работающих одновременно. Задание большого размера пула может существенно снизить скорость работы UI, например в списке может подтормаживать прокрутка. 
    • Значения по умолчанию - 5
  •  threadPriority(int) задает приоритет в системе (от 1 до 10) всех потоков, в которых выполняются задачи;
    • Значения по умолчанию - 4
  •  вызов denyCacheImageMultipleSizesInMemory() накладывает запрет на хранение в памяти разных размеров одной и той же картинки. Т.к в дисковом кэше хранятся полноразмерные картинки, а при загрузке в память они уменьшаются до размеров ImageView, в которых они должны отобразиться, то бывают случаи, что одну и ту же картинку необходимо отобразить сначала в маленькой вьюшке, а потом в большой. При этом в памяти будут хранится две Bitmap'ки разных размеров, представляющие одинаковую картинку. Это поведение по умолчанию. Инструкция  denyCacheImageMultipleSizesInMemory() обеспечивает удаление из кэша в памяти предыдущего размера загружаемой картинки.
  •  с помощью memoryCache(...) можно задать реализацию кэша в памяти. Можно воспользоваться готовыми решениями (все они представляют собой реализации кэша ограниченного размера, где при превышении размера кэша из него удаляется объект по определенному алгоритму):
    • FIFOLimitedCache (удаляется объект по принципу First-In-First-Out)
    • LargestLimitedCache (удаляется самый большой по размеру объект)
    • UsingAgeLimitedCache (удаляется объект с самой давней датой доступа)
    • UsingFreqLimitedCache (удаляется самый редко используемый объект)
    Либо можно подсунуть свой вариант кэша, реализовав интерфейс MemoryCacheAware<String, Bitmap>;
    • Значение по умолчанию - UsingFreqLimitedCache с ограничением памяти в 2 Мб
  •  memoryCacheSize(int) задает максимальный размер кэша в памяти. В этом случае используется кэш по умолчанию -  UsingFreqLimitedCache.
    • Значение по умолчанию - 2 Мб 
  • с помощью discCache(...) можно задать реализацию кэша на файловой системе. Можно воспользоваться готовыми решениями (в них файлы, соответствующие определенным URL-ам, именуются как хеш-коды этих URL-ов):
  • Либо можно подсунуть свою реализацию кэша, реализовав интерфейс DiscCacheAware.
  •  discCacheSize(int) задает максимальный размер кэша на файловой системе. В этом случае используется TotalSizeLimitedDiscCache.
  •  discCacheFileCount(int) задает максимальное количество файлов в дисковом кэше. В этом случае используется FileCountLimitedDiscCache.
  •  с помощью discCacheFileNameGenerator(...)  можно задать свой генератор имен для файлов закешированных на диске картинок: на входе получается URI картинки, на выходе надо выдать уникальное имя для файла (FileNameGenerator).
    Есть готовые варианты:
    • HashCodeFileNameGenerator - в качестве имени файла берется java хеш-код URI картинки
    • Md5FileNameGenerator - в качестве имени файла генерируется хеш-код по алгоритму MD5
    По умолчанию используется HashCodeFileNameGenerator
  • с помощью imageDownloader(...) можно задать свою реализацию загрузчика картинок: нужно представить свою имплементацию интерфейса ImageDownloader.
    Можно воспользоваться готовыми реализациями (по надобности их также можно унаследовать): По умолчанию используется BaseImageDownloader
  • с помощью defaultDisplayImageOptions(...) можно задать опции отображения картинок, которые будут использоваться для всех вызовов метода displayImage(...), где не были переданы кастомные опции. Подробнее, что это за эти опции, будет рассказано ниже.
  •  enableLogging() включает подробное логгирование процесса работы ImageLoader'a.
    Мы можем сами сконструировать объект конфигурации, либо довериться разработчику (т.е. мне) и воспользоваться конфигурацией по умолчанию:
ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(context);

    Итак, конфигурация создана. Теперь ею можно проинициализировать ImageLoader:
ImageLoader.getInstance().init(config);
Вот и все, ImageLoader готов к использованию. Но об этом Я расскажу уже в следующей статье.

Следующая статья: "Universal Image Loader. Part 3 - Usage"
Исходники проекта доступны здесь.

82 comments:

  1. Не могу понять почему происходит именно так. Возможно это известная ситуация. Используестя андроид 2.1. Вот кусок лога

    08-19 20:46:42.249: I/ImageLoader(469): Load image from Internet [http://img...jpg_48x80]

    08-19 20:46:42.500: I/global(469): Default buffer size used in BufferedInputStream constructor. It would be better to be explicit if an 8k buffer is required.

    На 4.1 картинки показываются. Возможно я что-то пропустил и есть минимальные требования к SDK?

    ReplyDelete
    Replies
    1. Минимальный API Level - 1.5. Не понял, в чем проблема? Не отображаются картинки на 2.1? В приведенных логах никаких ошибок не вижу. Или это все, что есть в логах?

      Delete
    2. Да именно так на android 2.1 картинки не показываются.
      Вот лог http://codepaste.ru/11565/
      Предпологаю что причина в фабрике SkImageDecoder::Factory returned null

      Начиная с android 2.2 картинки отображаются.

      Delete
    3. А пример проекта с GitHub (который UniversalImageLoaderExample) у вас работает на 2.1? Показывает картинки?

      Delete
  2. Скажите а можно добавить в loader свой httpclient? Например, если в приложении уже используется кастомный httpclient как синглтон, чтоб уже можно было его передать в ваш лоадер.

    ReplyDelete
    Replies
    1. Да, можно. Надо в конфигурацию передать свой imageDownloader. Можно воспользоваться HttpClientImageDownloader, который в конструктор принимает HttpClient.

      Delete
  3. Подскажите пожалуйста, можно ли указать путь к картинке, которая находится в assets ?
    т.к. при file:///android_asset/roks.png
    выдает ошибку
    /android_asset/roks.png (No such file or directory)
    хотя файл присутствует. при изменении на file:///mnt/sdcard/ все работает прекрасно
    в чем может быть ошибка ?

    ReplyDelete
    Replies
    1. Путь типа file://... указывает на файловую систему девайса. Assets папка лежит в приложении и не может быть доступна, как обычная папка на файловой системе.
      Тут есть два выхода:
      - в начале скопировать все файлы из assets на SD карту, а потом доступаться к ним через file://...
      - создать свой ImageDownloader (и засетить его в конфигурации), перегрузить InputStream getStreamFromOtherSource(URI imageUri), в нем по URI найти нужный вам файл в assets и перегнать его в InputStream. Для картинок из assets вызывать displayImage(...) c URI типа этого: "assets://roks.png".

      Скоро примерчик для второго случая включу в Example проект на GitHub.

      Delete
  4. Почему может не сохранять картинки в папке для кеша? пермишн стоит. папка существует (перепроверено много раз). Вот мои конфиги

    ImageLoaderConfiguration imageLoaderconfig = new ImageLoaderConfiguration.Builder(context)
    .memoryCacheExtraOptions(50, 50) // width, height
    .discCacheExtraOptions(50, 50, Bitmap.CompressFormat.PNG, 75)
    .threadPoolSize(3)
    .threadPriority(Thread.NORM_PRIORITY - 2)
    .denyCacheImageMultipleSizesInMemory()
    .offOutOfMemoryHandling()
    .memoryCache(new UsingFreqLimitedMemoryCache(5 * 1024 * 1024)) // 2 Mb
    .discCacheSize(15000)
    .discCacheFileCount(50)
    .discCache(new UnlimitedDiscCache(cacheDir))
    .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
    .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
    .enableLogging()
    .build();

    ReplyDelete
    Replies
    1. Readme читали? https://github.com/nostra13/Android-Universal-Image-Loader#useful-info
      Кэшировать или не кэшировать картинку выставляется в DisplayImageOptions. В простых опциях - DisplayImageOptions.createSimple() - кэширование ни в памяти, ни на диске не включено.

      Также вызовы в вашей конфигурации:
      .discCacheSize(15000)
      .discCacheFileCount(50)
      .discCache(new UnlimitedDiscCache(cacheDir))
      перекрывают друг друга. Информация об этом есть в Java доках, и в логах выводятся варнинги. Выбирайте что-то одно.

      Delete
    2. Ой ёй, извините что так сильно натупил.. Ушел читать доки.

      Delete
  5. Anonymous14/1/13 18:10

    Привет, спасибо за библиотечку.
    Есть один вопрос. У меня почему-то фотки (которые я снимаю и складываю во внутреннее хранилище) отображаются в неправильной ориентации. Они всегда повернуты на 90 градусов.

    Вы с этим не сталкивались? Может подскажете как это исправить?

    Спасибо.

    ReplyDelete
    Replies
    1. Привет. Скорее всего это из-за того, что поворот хранится в EXIF метаданных, а UIL никак не учитывает EXIF при отображении (пока). Вы можете создать свой BitmapDisplayer, где будете учитывать поворот, и засетить его в конфигурацию.

      Delete
    2. Хотя не, тут нужен доступ к файлу картинки. Тогда меняйте исходники или ждите, пока не добавится эта фича. Сколько ждать - не знаю.

      Delete
  6. Anonymous15/1/13 08:59

    Спасибо Сергей.

    ReplyDelete
  7. Anonymous19/1/13 11:59

    при быстрой прокрутки, картинки сбрасываються на дефолтные, как оставить картинки на своих местах ?

    ReplyDelete
  8. Подскажите пожалуйста есть ли возможность установить listener на загрузку ряда картинок? Чтоб, к примеру, ProgressDialog скрывался только после загрузки всей очереди , а не после каждой картинки

    ReplyDelete
    Replies
    1. Если только вы сами будете отслеживать это в листенере. Счетчик там какой-нибудь заведете или типа того, а листенере проверять, если счетчик равен кол-ву картинок - скрывайте ProgressDialog.

      Delete
  9. Кэширую изображению вот сюда: cacheDir = StorageUtils.getCacheDirectory(Context)
    как из этого каталога определенно получить изображение?
    Там они все храняться с непонятными именами..

    ReplyDelete
    Replies
    1. File image = DiscCacheUtil.findInCache(imageUri, imageLoader.getDiscCache());

      Delete
  10. Ссылка на изображение содержит кириллицу.
    В списке все отображается нормально. В ImageLoaderConfiguration указал memoryCache. Когда пытаюсь найти путь к изображению в кэшэ, использую этот метод
    DiscCacheUtil.findInCache(logoUrl.get(position), ImageLoader.getInstance().getDiscCache())
    он возвращает null.
    В чем может быть проблема?

    ReplyDelete
    Replies
    1. Читайте Readme - Useful Info, где и как включается кэш.
      В конфигурации вы лишь настраиваете кэши. А уж кэшировать или нет - это в DisplayImageOptions. И не забывайте разницу между кэшированием в памяти и на диске.

      Delete
    2. В DisplayImageOptions указал cacheInMemory()

      Delete
    3. Нет, вот все, что указал:
      options = new DisplayImageOptions.Builder()
      .showStubImage(R.drawable.stub_image)
      .showImageForEmptyUri(R.drawable.image_for_empty_url)
      .cacheInMemory()
      .cacheOnDisc()
      .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2).build();

      Delete
    4. Что-то так и не понял, в чем косяк... Может быть так, что это проблема заключается в том, что путь к картинке содержит кириллицу?

      Delete
    5. Конфигурация какая у вас?

      Delete
    6. File cacheDir = StorageUtils.getCacheDirectory(EngineBrowseByOnline.this);

      ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
      .memoryCacheExtraOptions(100, 100)
      .threadPoolSize(5)
      .threadPriority(Thread.MIN_PRIORITY + 2)
      .offOutOfMemoryHandling()
      .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
      .discCache(new UnlimitedDiscCache(cacheDir))
      .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
      .discCacheFileCount(100)
      .defaultDisplayImageOptions(DisplayImageOptions.createSimple()).enableLogging()
      .build();

      Delete
    7. Да, это проблема связана с кириллицей. Пофикшу в следующей версии.

      Пока решение для вас такое:

      String encodedUrl = Uri.encode(logoUrl.get(position), "@#&=*+-_.,:!?()/~'%");
      DiscCacheUtil.findInCache(encodedUrl, ImageLoader.getInstance().getDiscCache());

      Delete
    8. Спасибо!
      Жду следующей версии..

      Delete
  11. Anonymous18/3/13 14:08

    Сергей, спасибо! Отличная библиотека! Подскажите, а если мне не нужно сохранять картинки в кеше. Как правильно настроить объект?

    ReplyDelete
    Replies
    1. Где не нужно кэшировать? В памяти или на файловой системе?
      В DisplaytImageOptions есть .cacheInMemory() и .cacheOnDisc(). Если эти опции не включать, то и кэшироваться не будет.

      Delete
    2. Anonymous18/3/13 14:42

      ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ImagePagerActivity.this).build();
      imageLoader.init(config);

      DisplayImageOptions options = new DisplayImageOptions.Builder()
      .showImageForEmptyUri(R.drawable.ic_empty)
      .showImageOnFail(R.drawable.ic_error)
      .resetViewBeforeLoading().cacheOnDisc()
      .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
      .bitmapConfig(Bitmap.Config.RGB_565)
      .displayer(new FadeInBitmapDisplayer(300))
      .build();

      Я рисую изображение, показываю его пользователю с помощью DisplayImageOptions. После я рисую уже новое изображение, но сохраняю его с тем же именем и в тоге получаю старую картинку.

      Delete
    3. Anonymous18/3/13 14:45

      Все, понял свою ошибку. Надо было убрать .resetViewBeforeLoading().cacheOnDisc().

      Delete
  12. Anonymous21/5/13 13:30

    Сергей, привет. За библиотеку спасибо! Подскажи, пожалуйста, столкнулся с проблемой. Если изображение уже есть в кэше и по этому же url подсунуть другое изображение, то оно не загрузится, а отобразится старое из кэша.
    Вот, например: Есть файл site.ru/image/sample.jpg на котором изображена буква А, это изображение загрузили и сохранили в кэш. Потом по этому же адресу на веб сервере положили изображение с буквой Б (т.е. содержимое изменилось, а адрес нет). Так вот UIL не загружает новый файл, потому что url не изменился и показывает старое изображение из кэша. Как такое решить?

    ReplyDelete
    Replies
    1. Надо удалить сперва изображения из кэшей. Посмотри в сторону MemoryCacheUtil и DiscCacheUtil. Есть соответствующие имплементации кэшей (LimitedAge...), которые будут удалять закэшированные картинки через указанное время, тем самым форсируя их повторную загрузку с сервера.

      Delete
    2. Anonymous21/5/13 13:53

      LimitedAge.. видимо в более поздних версиях библиотеки появилось, у меня версия 1.5.2 :) Буду обновляться, спасибо

      Delete
  13. Здравствуйте!
    Подскажите, в чем может быть проблема.
    Сделал gridview с загрузкой изображений. url лежат в txt файле.
    Все работает, но при прокрутке экрана изображения меняются, на место старого ставится новое.

    Код:

    public class MainActivity extends Activity {


    ImageLoader imageLoader;
    GridView gv;
    ArrayList imageUrls = getUrlList();

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    imageLoader = ImageLoader.getInstance();
    imageLoader.init(ImageLoaderConfiguration.createDefault(getApplicationContext()));


    gv = (GridView) findViewById(R.id.gridView);
    gv.setAdapter(new ImageAdapter());


    public class ImageAdapter extends BaseAdapter {


    @Override
    public int getCount() {
    return imageUrls.size();
    }

    @Override
    public Object getItem(int position) {
    return null;
    }

    @Override
    public long getItemId(int position) {
    return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    final ImageView imageView;
    if (convertView == null) {
    imageView = (ImageView) getLayoutInflater().inflate(R.layout.grid_image, parent, false);
    } else {
    imageView = (ImageView) convertView;
    }

    imageLoader.displayImage(imageUrls.get(position), imageView);

    return imageView;
    }


    }

    public ArrayList getUrlList() {
    //Метод для считывания url изображений в ArrayList.
    }
    }

    ReplyDelete
    Replies
    1. В DisplayImageOptions надо включить .resetViewBeforeLoading().

      Delete
  14. FileCountLimitedDiscCache (ограниченный по размеру кэш)
    TotalSizeLimitedDiscCache (ограниченный по количеству файлов кэш)

    я так понимаю здесь перепутаны местами описания

    ReplyDelete
  15. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Ничем не могу помочь.

      Delete
    2. Ой, да я удалил уже коммент) У меня другой вопрос, как сделать принудительный кеш на сдкарту? Сейчас кеширует куда-то, но не понимаю куда, посмотреть только можно в свойствах приложения. А надо бы, чтобы кешировало в отдельную папку на диске.

      imageLoader = ImageLoader.getInstance(); // Получили экземпляр

      File cacheDir = StorageUtils.getOwnCacheDirectory(this, "UniversalImageLoader/Cache");

      ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
      //.memoryCacheExtraOptions(480, 800) // width, height
      //.discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // width, height, compress format, quality
      .threadPoolSize(5)
      .threadPriority(Thread.MIN_PRIORITY + 2)
      .denyCacheImageMultipleSizesInMemory()
      //.memoryCache(new UsingFreqLimitedMemoryCache(4 * 1024 * 1024)) // 2 Mb
      .discCache(new UnlimitedDiscCache(cacheDir))
      .discCacheFileNameGenerator(new HashCodeFileNameGenerator())
      .imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)
      .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
      .enableLogging()
      .build();

      imageLoader.init(config);

      Папки не создается, может я что-то делаю не так?

      Delete
    3. У вас разрешение на запись на карточку прописано?

      Delete
    4. Если имеется ввиду

      То да, прописано. Папка создается, но туда ничего не помещается. Может что-то стоит отключить в ImageLoaderConfiguration?

      Спасибо.

      Delete
    5. android.permission.WRITE_EXTERNAL_STORAGE

      Delete
    6. Значит вы наверное прочто не включаете кэширование. Его надо включать в display options.

      Delete
    7. Подскажите пожалуйста как это сделать? То, что я нашел DisplayImageOptions, там включил cacheOnDisc(), но мне выдает "The method cacheOnDisc() from the type DisplayImageOptions.Builder is deprecated". Что делать? И если я создам DisplayImageOptions, то мне всегда его надо добавлять при загрузке каждой картинки?

      Delete
    8. вроде разобрался, поставил в DisplayImageOptions - cacheOnDisc(true), теперь кеширует на диск. Буду проверять как работает)

      Delete
  16. Если в проекте надо грузить картинки с разными конфигами - в случае вашего синглтона это никак?

    ReplyDelete
    Replies
    1. А чем конфиги отличаться будут?

      Delete
  17. This comment has been removed by the author.

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. Anonymous2/10/13 20:36

    Когда вызывается ImageLoadingListener.onLoadingCancelled(String, View)? (я использую ViewPager, и иногда, при одновременной загрузке нескольких картинок, одна из них не не загружается, а вызывается onLoadingCancelled)

    ReplyDelete
    Replies
    1. ImageLoadingListener.onLoadingCancelled(...) вызывается когда ImageView была переиспользована для загрузки новой картинки.

      Delete
    2. как этого можно избежать? я столкнулся с подобной ошибкой..

      Delete
    3. Это не ошибка. Или у вас картинки не отображаются?

      Delete
  20. Здравствуйте! крутая штука, спасибо. Столкнулся с проблемой: если в системных настройках почистить кэш, то лоадер не находит папку cach, в логи пишет FileNotFoundException. Хотелось бы использовать именно эту папку для возможности чистки кэша из настроек. Есть ли решение кроме как изменять исходники?

    ReplyDelete
    Replies
    1. Здравствуйте. Я уже не помню точно, но папка вроде должна пересоздаваться, если ее вдруг удалили.

      Delete
    2. Создается она при старте приложения (при инициализации лоадера), а если удалить ее при запущенном приложении то в логи сыпет ексепшены а вместо фоток - черный экран. Буду искать решение, спасибо за ваши труды.

      Delete
    3. Пожалуйста.
      Какая версия библиотеки? Логика по воссоздания папки кэша точно есть: LoadAndDisplayImageTask.getImageFileInDiscCache()

      Delete
    4. Туплю - либа была 1.6.1 - в onResume() сам создавал папку cach. Скачал 1.8.6 - все решилось. Спасибо за терпение)

      Delete
  21. Здравствуйте, в одном из первых постов Вы написали, что добавили в пример как работать с assets. Если не трудно укажите пожалуйста где этот пример конкретно лежит, я не могу найти указанный Вами тут
    https://github.com/nostra13/Android-Universal-Image-Loader/issues/123 - ExtendedImageDownloader

    Спасибо

    ReplyDelete
    Replies
    1. Здравствуйте. Теперь UIL поддерживает загрузку из assets из коробки. Просто передавайте Uri типа "assets://..."

      Delete
  22. Здравствуйте, спасибо за библиотеку. Можно ли ее настроить чтобы также показывать thumbnails видео файлов? Вот вопрос на stackoverflow:
    http://stackoverflow.com/questions/20931585/is-it-possible-to-display-video-thumbnails-using-universal-image-loader-and-how

    Спасибо!

    ReplyDelete
    Replies
    1. Уже сделал. Я сделал для этого новый ImageDecoder, ответ можно посмотреть в том же линке.

      Delete
    2. Anonymous19/2/14 21:08

      Здравствуйте Сергей, спасибо за библиотеку. Как загрузить картины с хорошим качеством ?

      Delete
    3. Здравствуйте. Они загружаются в дисковый кэш в полном качестве, в кэш в памяти ресайзятся для экономии памяти. Чтобы не ресайзились используйте DisplayImageOptions.imageScaleType(ImageScaleType.NONE).

      Delete
  23. Anonymous19/2/14 23:01

    Попробовал поставить , но качество тоже самое
    DisplayImageOptions specialOptions = new DisplayImageOptions.Builder().cloneFrom(options).imageScaleType(ImageScaleType.NONE).build(); (LoadAndDisplayImageTask класс) и .cacheOnDisc().imageScaleType(ImageScaleType.NONE) (ImagePagerActivitu класс)

    ReplyDelete
    Replies
    1. Anonymous20/2/14 21:34

      Пожалуйста скажите где поставить эго

      Delete
  24. Anonymous22/2/14 12:25

    Здравствуйте Сергей , очень приятно что есть такие программисты как вы , я хотель получать фотографии с очень хорошим качеством , как мне это сделать попробовал DisplayImageOptions.imageScaleType(ImageScaleType.NONE) но все тоже самое , как мне быть где конкретно это поставить , может быть на еще что то поменять .Заранее Спасибо

    ReplyDelete
    Replies
    1. Здравствуйте, а что "то же самое"? Почему вы думаете, что показываются картинки не в полном качестве? Покажите свой конфиг, опции, сам код вызова imageLoader.

      Delete
    2. Anonymous22/2/14 22:41

      private boolean downloadSizedImage(File targetFile, int maxWidth, int maxHeight) throws IOException {
      // Download, decode, compress and save image
      ImageSize targetImageSize = new ImageSize(maxWidth, maxHeight);
      DisplayImageOptions specialOptions = new DisplayImageOptions.Builder().cloneFrom(options).imageScaleType(ImageScaleType.NONE).build(); //// Здесь
      Это в LoadAndDisplayImageTask и


      options = new DisplayImageOptions.Builder()
      .showImageForEmptyUri(R.drawable.ic_empty)
      .showImageOnFail(R.drawable.ic_error).resetViewBeforeLoading()
      .cacheOnDisc().imageScaleType(ImageScaleType.NONE) //// Здесь
      .bitmapConfig(Bitmap.Config.RGB_565)
      .displayer(new FadeInBitmapDisplayer(300)).build(); а это в ImagePagerActivity

      Delete
    3. Почему вы думаете, что показываются картинки не в полном качестве?

      Delete
    4. Anonymous22/2/14 22:52

      Я точно не уверен , а ImageScaleType.NONE поставлены в правильных местах ?

      Delete
    5. Исходники менять не нужно.
      Я так и не увидел вашей конфигурации и кода вызова displayImage().

      Delete
  25. Anonymous26/2/14 19:28

    Сергей Здравствуйте , спасибо за библиотеку , я отключил кэш .cacheInMemory(false) , .cacheOnDisc(false) в DisplayImageOptions но кэш заполняется в чем проблема ?

    ReplyDelete
  26. Здравствуйте, Сергей!
    Есть ли возможность использовать в качестве имени не MD5 от URL, а MD5 от самой картинки, от ByteArray, скажем.

    ReplyDelete
    Replies
    1. Здравствуйте. Есть возможность, но это будет неэффективно, т.к. вы должны будете делать дополнительный запрос. А вообще за имена отвечает FileNameGenerator, который можно передать в конфигурацию..

      Delete
    2. В том то и дело, что у меня есть URL и Hash, в случае, если Hash поменялся, мне необходимо загрузить новую картинку. Посему я бы хотел переложить эту работу на Ваш Loader, т.е давать ему хеш, который я получаю от сервера и URL, если хеш той картинки, что я получаю от сервера не совпадает с тем что у меня есть, то я по тому же самому URL загружаю новую. Расскажите, пожалуйста, какая есть для этого возможность.

      Delete