Комментарии 28
Отличное сравнение.
Для загрузки картинок под Android есть еще библиотека glide (https://github.com/bumptech/glide).
Интересно, насколько она эффективна по сравнению с Picasso.
Для загрузки картинок под Android есть еще библиотека glide (https://github.com/bumptech/glide).
Интересно, насколько она эффективна по сравнению с Picasso.
Допишу на выходных тесты этих 2-х либ. Зафейворите репозиторий — выложу отчет туда.
А как у перечисленных библиотек с такими функциям/проблемами:
1. Картинка грузится с закрытого сервера, требуется авторизация, кроме того с запросом передаются специальные HTTP-заголовки, также как и с ответом — и всё это надо гибко обработать
2. Картинка грузится медленно, приложение должно быть возможно свернуть/восстановить (короче, есть ли там работа в режиме фонового service-а)?
1. Картинка грузится с закрытого сервера, требуется авторизация, кроме того с запросом передаются специальные HTTP-заголовки, также как и с ответом — и всё это надо гибко обработать
2. Картинка грузится медленно, приложение должно быть возможно свернуть/восстановить (короче, есть ли там работа в режиме фонового service-а)?
1. С UIL-ом такая комбинация точно работает. В конфигурации можно установить кастомный ImageDownloader, который экстендит библиотечный. Там и можно настроить хедеры и выполнить авторизацию перед запросом. Я использую в одном проекте. А вот с Picasso — не уверен, нужно смотреть.
2. Нужно тестировать. Но, поскольку, библиотека использует пул потоков для загрузки — то скорее всего Threads никуда не деваются при сворачивании Activity. А если нужно остановить\восстановить запросы по onStart()/onPause() — обе библиотеки поддерживают такую возможность.
2. Нужно тестировать. Но, поскольку, библиотека использует пул потоков для загрузки — то скорее всего Threads никуда не деваются при сворачивании Activity. А если нужно остановить\восстановить запросы по onStart()/onPause() — обе библиотеки поддерживают такую возможность.
Я использую UIL для загрузки картинок в твиттер клиенте Robird.
Каждый твит имеет как минимум 1 картинку — аватарку пользователя и может еще отображать превью картинок с разных сервисов.
UIL работает очень плавно и быстро подгружает картинки. Никаких поддергиваний при скроле. Вот моя конфигурация:
К сожалению при использовании Picasso у меня были проблемы со скоростью загрузки картинок. Правда это было в первых версия библиотеки. Как она сейчас работает в плане скорости загрузки и отображения картинок?
Каждый твит имеет как минимум 1 картинку — аватарку пользователя и может еще отображать превью картинок с разных сервисов.
UIL работает очень плавно и быстро подгружает картинки. Никаких поддергиваний при скроле. Вот моя конфигурация:
Executor downloadExecutor = Executors.newFixedThreadPool(5);
Executor cachedExecutor = Executors.newSingleThreadExecutor();
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int memClass = am.getMemoryClass();
final int memoryCacheSize = 1024 * 1024 * memClass / 8;
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(android.R.color.transparent)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.cacheInMemory(true)
.cacheOnDisc(true)
.build();
File cacheDir = StorageUtils.getCacheDirectory(this);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.taskExecutor(downloadExecutor)
.taskExecutorForCachedImages(cachedExecutor)
.memoryCache(new UsingFreqLimitedMemoryCache(memoryCacheSize)) // 2 Mb
.discCache(new TotalSizeLimitedDiscCache(cacheDir, 52428800))
.imageDownloader(new BaseImageDownloader(this, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)
.defaultDisplayImageOptions(options)
.build();
К сожалению при использовании Picasso у меня были проблемы со скоростью загрузки картинок. Правда это было в первых версия библиотеки. Как она сейчас работает в плане скорости загрузки и отображения картинок?
А почему именно такой объем памяти?
memClass / 8 — почему именно этот коэффициент?
Всегда волновал вопрос, как правильнее высчитать размер кеша.
int memClass = am.getMemoryClass();
final int memoryCacheSize = 1024 * 1024 * memClass / 8;
memClass / 8 — почему именно этот коэффициент?
Всегда волновал вопрос, как правильнее высчитать размер кеша.
Коэффициент был выбран опытным путем. Picasso использует коэффициент равный 7. Вроде и у них и у меня все ок с этим)
developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache
Note: In this example, one eighth of the application memory is allocated for our cache. On a normal/hdpi device this is a minimum of around 4MB (32/8). A full screen GridView filled with images on a device with 800x480 resolution would use around 1.5MB (800*480*4 bytes), so this would cache a minimum of around 2.5 pages of images in memory.
Есть идея, как кодом вычислить «подергивания»? Если что — реализую, и будет ещё один Benchmark.
Поддергивания только в реальном использовании можно заметить. Бенчмаркам не поддается))
У вас в реальных проектах picasso используется? есть списки с картинками?
У вас в реальных проектах picasso используется? есть списки с картинками?
Пока что UIL. На тест Picasso подтолкнула постоянная проблема с бесконечной сборкой мусора и OutOfMemory на старых устройствах. Но планирую пробу заинтегрить Picasso.
Еще как я понял загрузку картинок при скроле нельзя тормозить в picasso?
можно вот так: Настройки > Для разработчиков > Запись времени работы GPU
В UIL есть еще баг который приводит к кешированию картинок 2 раза.
Все потому, что используют размер вью в качестве ключа для кеша, и если у вас ImageView, например, match_parent/wrap_content, то в первый проход размер не будет известен, а будет только во второй, как результат, получаем:
1. дублирующиеся картинки в памяти (и на диске?)
2. и бонусом мигание картинок при прокрутке.
p.s. баг тикет на github issues/376
Все потому, что используют размер вью в качестве ключа для кеша, и если у вас ImageView, например, match_parent/wrap_content, то в первый проход размер не будет известен, а будет только во второй, как результат, получаем:
1. дублирующиеся картинки в памяти (и на диске?)
2. и бонусом мигание картинок при прокрутке.
p.s. баг тикет на github issues/376
Дублированиения на диске нет. Дублирование в памяти можно предотвратить с помощью опции конфигурации ImageLoaderConfiguration.denyCacheImageMultipleSizesInMemory().
А проблема с первым проходом при match_parent/wrap_content — да, существует. На данный момент выход — это вызывать ImageLoader через post():
А проблема с первым проходом при match_parent/wrap_content — да, существует. На данный момент выход — это вызывать ImageLoader через post():
imageView.post(new Runnable() {
@Override
public void run() {
imageLoader.displayImage(...);
}
});
Я для себя сделал грязный хак, который решает все эти проблемы разом:
/* com.nostra13.universalimageloader.core.ImageLoader:194 */
String memoryCacheKey = uri; // MemoryCacheUtil.generateKey(uri, targetSize);
Не очень красиво, за то эффективно. Но будет здорово, если можно будет это решить как то в конфигурации по умолчанию, без лишних движений.
/* com.nostra13.universalimageloader.core.ImageLoader:194 */
String memoryCacheKey = uri; // MemoryCacheUtil.generateKey(uri, targetSize);
Не очень красиво, за то эффективно. Но будет здорово, если можно будет это решить как то в конфигурации по умолчанию, без лишних движений.
по поводу post runnable
Ну вот у нас есть сетка с картинками, видно сразу 20+ картинок, то есть мне нужно запостить 20 runnable просто что бы подождать пока будет известен размер для ImageView? А потом мне что нужно хранить флаг, и больше это не делать, или каждый раз при прокрутке пулять 20 + runnable?
Как то это все не правильно.
Ну вот у нас есть сетка с картинками, видно сразу 20+ картинок, то есть мне нужно запостить 20 runnable просто что бы подождать пока будет известен размер для ImageView? А потом мне что нужно хранить флаг, и больше это не делать, или каждый раз при прокрутке пулять 20 + runnable?
Как то это все не правильно.
В документации по UIL написано, что порядок определения размеров Bitmap следующий:
Соответственно, если размеры ImageView, в который нужно положить изображение, никак не ограничить (match_parent/wrap_content не в счет), произойдет загрузка изображения, смасштабированного под ширину/высоту устройства. Я для себя проблему расчета размера Bitmap'ов при загрузке оных в GridView решил установкой параметров maxWidth/maxHeight, принадлежащих отдельным ImageView, в нужные мне значения.
- Get actual measured width and height of ImageView
- Get android:layout_width and android:layout_height parameters
- Get android:maxWidth and/or android:maxHeight parameters
- Get maximum width and/or height parameters from configuration (memoryCacheExtraOptions(int, int) option)
- Get width and/or height of device screen
Соответственно, если размеры ImageView, в который нужно положить изображение, никак не ограничить (match_parent/wrap_content не в счет), произойдет загрузка изображения, смасштабированного под ширину/высоту устройства. Я для себя проблему расчета размера Bitmap'ов при загрузке оных в GridView решил установкой параметров maxWidth/maxHeight, принадлежащих отдельным ImageView, в нужные мне значения.
Вообще это какой то не правильный подход. Зачем ограничивать размеры вью? Что бы потом изобретать велосипед с ручным расчетом на разных размерах экранов? Для этого и придуман wrap_content/match_parent/ layout_weight.
Все что написано вами выше, должно быть опционально и выключено по умолчанию. Потому что, большинство рест апи позволяет:
1. тянуть картинки разного качества, а это значит что нам не нужно дополнительно, что либо еще делать на клиентах. Экономим память, диск, сеть, батарейку и тд.
2. ImageView, без труда может и сам масштабировать картинку, если нужно.
Итого, самый популярный способ показать картинки: GridView с автоматическим расположением картинок (количество столбцов, размер и тд), и uil тут явно не ваш друг.
Все что написано вами выше, должно быть опционально и выключено по умолчанию. Потому что, большинство рест апи позволяет:
1. тянуть картинки разного качества, а это значит что нам не нужно дополнительно, что либо еще делать на клиентах. Экономим память, диск, сеть, батарейку и тд.
2. ImageView, без труда может и сам масштабировать картинку, если нужно.
Итого, самый популярный способ показать картинки: GridView с автоматическим расположением картинок (количество столбцов, размер и тд), и uil тут явно не ваш друг.
Кстати, какие версии библиотек использовались в бенчмарке? Это важно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Экономим память: Picasso vs UniversalImageLoader