Так сложилось, что я люблю маленькие верткие библиотеки, которые с одной стороны — легко расширять, а с другой — удобны в использовании.

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

Так как человек я по натуре ленивый — решил пойти проторенным путем — открыл пример от гугла Loading Large Bitmaps Efficiently и решил вырезав из него все ненужное — получить с одной стороны легко расширяемую, а с другой стороны максимально эффективную библиотеку.

Так как кто как не эти чуваки лучше знают как грузить битмапы?

Так и получился Малевич:

image

Спойлер:

malevich.load(mImageUrl).into(mImageView);


Вырезав, все ненужное и поправив глючки (их было чертовски мало) я начал добавлять нужное)

Наверное не сложно догадаться, какой библиотекой я вдохновлялся упрощая синтаксис.

Но давайте собственно к библиотеке.
Есть два режима использования.
Режим для гагар:

// init
Malevich malevich = new Malevich.Builder(this).build();

// use
malevich.load(mImageUrl).into(mImageView);
//где mImageUrl - Bitmap или BitmapDrawable или Resource id  или HttpUrl или Путь к файлу

И режим для тех, кому за 30:

Memory and disk caching params

ImageCache.ImageCacheParams cacheParams = new ImageCache.ImageCacheParams(this, "dir");
        cacheParams.memoryCacheEnabled = true; //Enable memory cache
        cacheParams.setMemCacheSizePercent(0.4f);  //Percent of available memory for cache
        cacheParams.compressQuality = 90; // Compress quality
        cacheParams.compressFormat = Bitmap.CompressFormat.PNG; // Compress format
        cacheParams.diskCacheEnabled = true; // Use disk cache
        cacheParams.diskCacheSize = 10485760; // Disk cache size

Malevich Builder

malevich = new Malevich.Builder(this)
        .debug(true) // write log
        .maxSize(1024) // max size of image in px
        .LoadingImage(R.drawable.some) // preloader image or recource
        .CacheParams(casheParams) // custom cache
        .build();

Loading image

Transform image after loading with prebuild utils or custom method:

malevich.load(url).width(mItemHeight).height(mItemHeight).imageDecodedListener(new Malevich.ImageDecodedListener() {
                    @Override
                    public Bitmap onImageDecoded(String data, int reqWidth, int reqHeight, Bitmap bitmap) {

                        // Get squared bitmap and transform it to circle
                        return Malevich.Utils.getSquaredCircleBitmap(bitmap,reqWidth);
                    }
                }).into(imageView);


Но в общем и целом, целью проекта не было сделать пикассо или глайд на гугловском движке. Я добавил только самые необходимые утилиты, постоянно использующиеся в нелегкой жизни фрилансера — дай квадрат из картинки, дай круг и т.п. Так как хотелось сохранить легкую расширяемость и не превратиться в какую-нибудь прости господи фреску от сами знаете кого.

Да, предмет моей особой гордости это то, что библиотека содержит меньше десятка классов и 0 (Зиро) зависимостей.

Ну и всякие формальности:
— настраиваемый, нежнейший лру кэш в памяти
— отключаемый дисковый кэш
— перекрытие событий загрузки, ошибок
— управление потоками
— няшные утилиты, удобный билдер
— единственная библиотека эффективно переиспользующая память согласно лучшим рекомендациям от Гугла)

В общем, если вам когда нибудь придется грузить тонны картинок в хитро закрученном воркфлоу со всякими кастомными штуками — вспомните о Малевиче.

Ссылка на гитхаб: github.com/recoilme/malevich

Буду рад контрибьюторам!

Комментарии (15)


  1. maeln0r
    09.07.2015 19:46
    +1

    Спасибо, большое. То, что надо!


  1. svartalf
    09.07.2015 21:53

    Сразу вспоминается «коллега» Picasso: square.github.io/picasso


  1. devnseven
    10.07.2015 00:59
    +3

    «нежнейший лру кэш» — убило)


  1. 0leGG
    10.07.2015 01:00
    +6

    Дайте угадаю — вместо всех картинок чёрные квадраты рисуются?


    1. recompileme Автор
      10.07.2015 10:40
      +2

      была идея так пошутить если не удалось загрузить картинку, но сдержался)


  1. Evgenij_Popovich
    13.07.2015 12:40

    Не нашел в коде поддержки EXIF Orientation. Вероятно, кому-то эта опция будет полезной.


    1. recompileme Автор
      21.07.2015 11:10

      Вы правы, надо бы включить


  1. Bringoff
    13.07.2015 21:13

    Использую Glide, пока все устраивает. Я склонен верить гуглу, который её порекомендовал. Возможно, «нежнейший лру кэш» меня будет прельщать, когда мне будет за 30, но тогда и android-а может уже не быть :D


    1. recompileme Автор
      21.07.2015 11:09

      А где он ее порекомендовал, можно ссылку?


      1. Bringoff
        21.07.2015 11:19

        Как минимум, вот так.


        1. recompileme Автор
          21.07.2015 11:31

          Это не рекомендация, это вполне типичный для гугла фейл. Вместо того чтобы написать свой удобный врапер над urlConnection и менеджер загрузки битмапов — юзаются левые Basic HTTP Client / Glide в проекте — примере. Стыдно.


  1. BOOMik
    14.07.2015 23:24

    Интересно попробовать… Какая минимальная поддерживаемая версия API?
    И залить бы в MAVEN…


    1. recompileme Автор
      21.07.2015 11:07

      Тестил на 11, поэтому поставил ее. Но заглушки в коде стоят и для глючков второго андроида, так что по идее должно работать на любом апи одинаково.


  1. danikula
    17.07.2015 15:02

    Не совсем понял, в чем преимущества над уже хорошо зарекомендовавшими себя решениями (fresco, UIL, Picasso)? В минимализме или еще в чем-то? Хотелось бы услышать развернутое сравнение с конкурентами: наличие/отсутствие фич, перфоманс, размер и пр.


    1. recompileme Автор
      21.07.2015 11:04
      +1

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

      — fresco
      Во первых у меня предвзятое отношение к продуктам данной компании. Фейсбук, пожалуй единственное приложение, которое умудряется глючить и лагать среди равных себе по охвату аудитории на моем нексус 5. Сообщение «Отстутствует соедениение» — стало настолько привычным, что я уже даже не кликаю по уведомлениям. Вероятность корректного получения токена при интеграции с фесбук, была вычисленна экспериментально и составляет 90%. Т.е. в 1 из 10 случаев вместо токена вернется ничто. Но если отбросить предвзятость:
      + поддержка webp и gif из коробки
      + хитрое выделение памяти
      — совершенно некастомизируемо.
      — исходный код нечитаем
      Используется кастомная вьюха для рендеринга битмапов, которая хоть и является наследницей imageview — не переиспользуема со стороны. Например в процессе загрузки вам нужно рисовать кружок с процентом загрузки как принять в iOs — вы не можете тупо написать setBitmap вьюхе, потому что это сломает их процесс: frescolib.org/docs/gotchas.html#_

      — picasso

      + простой интерфейс
      — слабая функциональность
      — неэффективное управление памятью ( не используются inBitmaps)

      Подходит только для примитивных задач. Нельзя ни поставить загрузку на паузу, ни задать размеры кешей, да практически ничего нельзя. Насколько я понял проект заброшен и Джейк Вартсон переключился на Glide

      — UIL

      + хороший компромисс между функциональностью и простотой
      — неэффективное управление памятью (предположительно)

      Неплохое развитие идей Федора Власова, если честно глубоко не смотрел, потому что оригинал Федора мне ближе, его легче было подстраивать под себя

      Вобщем я позиционирую малевича как нечто среднее между uil и picasso. По хорошему надо бы дописать функционала, не изгадив простоту, и будет неплохая библиотека. Пока она чуть лучше picasso, но уступает по функционалу и количеству фич всем остальным.