Что такое Picasso и как использовать его с Kotlin

Сегодня сложно найти Android-приложение совсем без картинок: аватарки, баннеры и иконки должны загружаться быстро и не тормозить интерфейс. Picasso — это библиотека от компании Square, которая берёт на себя всю грязную работу: скачивание, кэширование, изменение размеров и показ изображений в одну строчку кода. В этом руководстве я покажу, как использовать picasso kotlin в реальном проекте — от подключения зависимости до обработки ошибок и плавной прокрутки списков.


Коротко о библиотеке

Square разработала Picasso как минималистичный инструмент для загрузки картинок. Он добавляет к APK около 121 КБ и содержит примерно 849 методов — очень легковесный по сравнению с аналогами. Библиотека автоматически кэширует изображения в оперативной памяти и на диске, корректно обрабатывает переиспользование View в списках и позволяет трансформировать картинки на лету. Для простых приложений, где не нужна анимация GIF или сверхсложные трансформации, Picasso остаётся отличным выбором даже в 2026 году.


Подключение к проекту

Первым делом добавляем зависимость в build.gradle.kts модуля app. Если используете Groovy-синтаксис, запись будет немного другой, но смысл тот же.

dependencies {
    implementation("com.squareup.picasso:picasso:2.8")
}

После синхронизации Gradle не забудьте прописать разрешение на интернет в AndroidManifest.xml, иначе загрузка изображений будет падать с ошибкой.

<uses-permission android:name="android.permission.INTERNET" />

Простейший пример загрузки

Чтобы загрузить изображение по URL и отобразить его в ImageView, достаточно одной строчки. Библиотека сама запустит фоновый поток, скачает картинку, сохранит в кэш и покажет результат.

Picasso.get()
    .load("https://example.com/photo.jpg")
    .into(imageView)

Этот код можно разместить прямо в onCreate Activity. Никакой ручной работы с потоками, никаких дополнительных настроек — всё происходит само.


Placeholder и обработка ошибок

Пока изображение загружается, полезно показать заглушку, чтобы экран не выглядел пустым. Если загрузка провалилась, пользователь тоже должен видеть какое-то изображение, а не пустое место. Для этого у Picasso есть методы placeholder и error.

Picasso.get()
    .load("https://example.com/photo.jpg")
    .placeholder(R.drawable.ic_placeholder)
    .error(R.drawable.ic_error)
    .into(imageView)

Если нужно получить доступ к загруженному Bitmap напрямую, используйте интерфейс Target. Это пригодится, когда картинку надо сохранить локально или передать в другой компонент.

Picasso.get()
    .load(url)
    .into(object : Target {
        override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) {
            imageView.setImageBitmap(bitmap)
        }
        override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
        override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
    })

Второй параметр Picasso.LoadedFrom подскажет, откуда взялась картинка: из памяти, с диска или из сети.


Изменение размера и обрезка

Если загружать на слабый телефон огромное фото с сервера, приложение может упасть с OutOfMemoryError. Чтобы избежать этого, указывайте конкретные размеры через resize и выбирайте способ масштабирования: centerCrop или centerInside.

Picasso.get()
    .load("https://example.com/large.jpg")
    .resize(800, 600)
    .centerCrop()
    .into(imageView)

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


Работа с RecyclerView

В списках, где View переиспользуются, старая загрузка может наложиться на новую. Picasso умеет автоматически отменять запрос к ImageView, если тот был переиспользован для другого элемента. Никакого дополнительного кода не требуется — просто вызывайте load().into() в методе адаптера.

Однако если вам нужна более продвинутая логика вроде паузы загрузки во время быстрой прокрутки, можно подключить PicassoScrollListener и управлять тегами вручную. Но для большинства сценариев достаточно стандартного поведения «из коробки».


Трансформации изображений

Picasso позволяет трансформировать изображение перед показом: скруглить углы, сделать чёрно-белым, наложить фильтр. Для этого используется абстрактный класс Transformation, который нужно реализовать.

class CircleTransform : Transformation {
    override fun transform(source: Bitmap): Bitmap {
        val size = minOf(source.width, source.height)
        val squaredBitmap = Bitmap.createBitmap(source, 0, 0, size, size)
        if (squaredBitmap != source) source.recycle()
        val bitmap = Bitmap.createBitmap(size, size, source.config ?: Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val paint = Paint().apply {
            isAntiAlias = true
            shader = BitmapShader(squaredBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        }
        canvas.drawCircle(size / 2f, size / 2f, size / 2f, paint)
        squaredBitmap.recycle()
        return bitmap
    }

    override fun key(): String = "circle"
}

Picasso.get()
    .load(url)
    .transform(CircleTransform())
    .into(imageView)

Метод key() возвращает уникальный строковый идентификатор трансформации. Он нужен для корректной работы кэша: если один и тот же URL загружается с разными трансформациями, Picasso должен различать результаты.


Управление кэшем

По умолчанию Picasso использует LRU-кэш в памяти (около 15% доступной оперативной памяти приложения) и дисковый кэш объёмом от 5 до 50 МБ в зависимости от свободного места на устройстве. В большинстве случаев этого достаточно, но иногда требуется ручное управление.

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

Picasso.get()
    .load(url)
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
    .into(imageView)

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


Сравнение с другими библиотеками

В 2025-2026 годах основными конкурентами Picasso остаются Glide, Coil и Fresco. У каждой библиотеки своя ниша, и я собрал ключевые отличия в таблицу.

Критерий Picasso Glide Coil
Размер библиотеки ~121 КБ, 849 методов ~440 КБ, 2678 методов ~2000 методов (легче Glide)
API Минималистичный, легко освоить Богатый, много настроек Kotlin-ориентированный, поддержка корутин из коробки
Скорость загрузки ~705 мс ~676 мс ~432 мс (лидер по скорости)
Поддержка GIF Требует сторонних решений Встроенная Через coil-gif
Jetpack Compose Только XML / View Через accompanist или compose-адаптер Нативная поддержка из коробки

Если у вас проект на чистом Kotlin с Jetpack Compose, лучше сразу взять Coil. Если проект legacy-формата с XML-вёрсткой и вы цените простоту, Picasso будет отличным выбором. Glide подойдёт для больших приложений со сложными требованиями к трансформациям и анимациям.


Практическое задание

Чтобы закрепить навык, выполните простое упражнение: создайте приложение с полем ввода URL, кнопкой «Загрузить» и ImageView. При нажатии на кнопку вызывайте Picasso с введённым адресом, добавьте placeholder и сообщение в лог при ошибке. Затем попробуйте добавить список из пяти фотографий в RecyclerView и убедитесь, что прокрутка остаётся плавной. Это отнимет 20–30 минут, но даст полное понимание работы библиотеки на практике.


Коротко о главном

Picasso — это лёгкая и надёжная библиотека для загрузки изображений в Android на Kotlin. Она идеально подходит для простых и средних проектов, где не нужны анимации GIF и интеграция с Compose. Подключение занимает пару минут: добавили зависимость в Gradle, прописали INTERNET в манифесте и вызываете Picasso.get().load(url).into(imageView). Автоматическое кэширование, отмена запросов при переиспользовании View и встроенные трансформации делают Picasso проверенным инструментом, который будет работать даже через несколько лет. Освойте её сегодня — и загрузка картинок перестанет быть проблемой.