Экономьте Память: Пикассо Против Universalimageloader

Привет Android-разработчикам! Думаю, каждый из нас сталкивался с загрузкой изображений по URL. Самый простой способ решить эту проблему — использовать готовую стороннюю библиотеку.

Как правило, одним из таких готовых решений является Universal Image Loader (UIL), Picasso. Когда я спрашиваю разработчика, почему он выбрал ту или иную библиотеку, обычно получаю разные ответы.

Например, «У Picasso/UIL нет проблем с утечками памяти», или «Square делает только правильные вещи», или просто «Ну, я использую UIL, он работает и хорош».

Итак, мне было интересно: какая из этих двух библиотек оптимально использует память? Я использую UIL, и у меня проблема с OutOfMemory на старых устройствах.

Возможно, Пикассо – лекарство? Так родилась идея этого бенчмарка.

Цель тестирования: определить, какая библиотека (UIL или Picasso) использует минимум памяти устройства.

Тестовые случаи: — Загрузка небольших изображений (240x240) — Загрузка больших изображений (> 400 пикселей любого размера) — Загрузка больших изображений и преобразование их размера в размеры ImageView. — Загрузка небольших изображений и отображение их в виде круглой картинки - Загрузка больших изображений и их отображение в конфигурации RGB565. Тестовая процедура: В качестве списка мы используем GridView шириной в 2 столбца.

Адаптер настраивается отдельно для каждого тестового примера.

Мы отправляем в адаптер список заранее подготовленных URL-адресов, создавая тем самым одинаковые условия тестирования.

С периодом в 1 секунду список автоматически делает один проход вниз, а затем вверх с шагом в 4 изображения.

На каждом этапе измеряется память, используемая приложением.

Мы измеряем используемую память в 3 этапа для каждого тестового примера: - первый запуск - с очисткой кеша приложения; — второй запуск: без закрытия приложения после первого прохода; - третий запуск - после повторного открытия приложения без очистки кеша.

В конце тестового примера я дополнительно записал размер кэша, что также важно для старых устройств.

Исходники бенчмарков можно найти по ссылке github.com/artemmanaенко/ImageLoadersTest .

Проект построен под Gradle. Итак, ниже приведены результаты для каждого тестового примера.

Ось Y — это объем памяти, используемый приложением в МБ.

Ось X — время тестового примера.



Загрузка небольших изображений


Экономьте память: Пикассо против UniversalImageLoader

Размер кэша: Пикассо=1,39 МБ, UIL=1,17 МБ

Загрузка больших изображений


Экономьте память: Пикассо против UniversalImageLoader

Размер кэша: Пикассо=3,67 МБ, UIL=5,44 МБ

Загрузка больших изображений и преобразование в размер ImageView


Экономьте память: Пикассо против UniversalImageLoader

Размер кэша: Пикассо=3,67 МБ, UIL=5,44 МБ

Загрузка небольших изображений и обрезка их до круглого изображения


Экономьте память: Пикассо против UniversalImageLoader

Размер кэша: Пикассо=1,39 МБ, UIL=1,17 МБ

Загрузка больших изображений и их отображение в конфигурации RGB565.


Экономьте память: Пикассо против UniversalImageLoader

Меня впечатлили результаты экспериментов с большими картинками, и я решил, что стоит попробовать настроить конфигурацию UIL. Чтобы не перегружать память кешем, я попробовал отключить UIL-кеш в оперативной памяти.

И, как вариант, установите размер кэшированного изображения не более половины экрана.



Экономьте память: Пикассо против UniversalImageLoader

По итогам эксперимента я сделал следующие выводы:

  • Если ваши списки работают с небольшими изображениями (сопоставимыми с размером ImageView), выбор библиотеки для вас не важен.

    Пикассо создает немного больший дисковый кэш, используя примерно такой же объем оперативной памяти.

  • Пикассо показал потрясающие результаты управления памятью при работе с большими изображениями.

    Похоже, что UIL сохраняет исходное изображение в памяти.

    Пикассо сохраняет уже преобразованный размер изображения.

    Вот почему дисковый кэш Пикассо значительно меньше.

  • UIL может работать с той же эффективностью, что и Пикассо, если его дополнительно настроить.

    Например, ограничить размер кэша в памяти.

    Или, как в одном из тестов, вручную ограничить размер кэшируемых фотографий.

    Второй метод может быть неприменим, поскольку он устанавливает глобальную конфигурацию ImageLoader.

  • Работать с круглыми аватарами «дешевле» через Пикассо.

    Но, опять же, из-за того, что я вручную вызвал recycle() для исходного растрового изображения.

    То же действие можно выполнить в UIL, установив переопределенный BitmapDisplayer.

  • Picasso чрезвычайно прост в использовании и эффективно работает с памятью прямо из коробки.

    Вот как выглядит инициализация и загрузка библиотек: Пикассо

      
      
      
       

    public class PicassoSquareFitAdapter extends BaseBenchmarkAdapter { public PicassoSquareFitAdapter(Context context, IUrlListContainer urlListContainer) { super(context, urlListContainer); } @Override protected void loadImage(ImageView imageView, String url) { Picasso.with(context).

    load(url).

    fit().

    into(imageView); } }

    УИЛ

    public class UILSquareFitAdapter extends BaseBenchmarkAdapter { private DisplayImageOptions options; public UILSquareFitAdapter(Context context, IUrlListContainer urlListContainer) { super(context, urlListContainer); ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(context); ImageLoader.getInstance().

    init(config); options = new DisplayImageOptions.Builder() .

    imageScaleType(ImageScaleType.EXACTLY) .

    resetViewBeforeLoading(true) .

    cacheInMemory(true) .

    cacheOnDisc(true) .

    build(); } @Override protected void loadImage(ImageView imageView, String url) { ImageLoader.getInstance().

    displayImage(url, imageView, options); } }

  • Есть у Пикассо и минус: трансформации изображений и преобразование в RGB565 нужно делать на самописных занятиях.

    РаундТрансформация

    public class RoundTransformation implements Transformation { @Override public Bitmap transform(Bitmap source) { int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); if (squaredBitmap != source) { source.recycle(); } Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); paint.setShader(shader); paint.setAntiAlias(true); float radius = size / 2f; canvas.drawCircle(radius, radius, radius, paint); squaredBitmap.recycle(); return bitmap; } @Override public String key() { return "circle"; } }

    Config565Трансформация

    public class Config565Transformation implements Transformation { @Override public Bitmap transform(Bitmap source) { Bitmap resultBitmap = Bitmap.createBitmap( source.getWidth(), source.getHeight(), Bitmap.Config.RGB_565 ); Canvas canvas = new Canvas(resultBitmap); Paint paint = new Paint(); paint.setFilterBitmap(true); canvas.drawBitmap(source, 0, 0, paint); source.recycle(); return resultBitmap; } @Override public String key() { return "Config565Transformation"; } }

    Для себя я сделал вывод: проекты нужно переводить в Пикассо.

    В моем случае это решит проблему чрезмерного использования памяти.

    Надеюсь, этот пост будет полезен и вам!

Теги: #универсальный загрузчик изображений #picasso #Android #разработка для Android #загрузчики изображений #разработка для Android #загрузка изображений #память #разработка для Android
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.