Coil — چیست، مفاهیم کلیدی و ImageLoader در Android

نویسنده: IT Sectr منتشر شده: 2026-05-05 زمان مطالعه: 9 دقیقه

Coil — کتابخانه‌ای برای بارگذاری تصاویر در Android است که به زبان Kotlin نوشته شده و بر پایه کوروتین‌ها ساخته شده است. به گفته مستندات رسمی، این کتابخانه از Memory Cache، Disk Cache و تبدیل‌های با شتاب سخت‌افزاری پشتیبانی می‌کند. Coil با حداقل اندازه APK (حدود 150 KB) و سازگاری کامل با Jetpack Compose متمایز می‌شود.

نکات اصلی

  • Coil — کتابخانه بارگذاری تصاویر در Android که از Kotlin Coroutines و Kotlin Serialization استفاده می‌کند.
  • ImageLoader — مؤلفه مرکزی که درخواست‌ها، ذخیره‌سازی و تبدیل تصاویر را مدیریت می‌کند.
  • Memory Cache تصاویر بیت‌مپ رمزگشایی شده را در RAM برای دسترسی فوری ذخیره می‌کند.
  • Disk Cache فایل‌های فشرده را روی دیسک برای کار آفلاین و کاهش ترافیک ذخیره می‌کند.
  • Jetpack Compose — کتابخانه از AsyncImage و SubcomposeAsyncImage برای UI اعلانی پشتیبانی می‌کند.

Coil چیست؟

Coil (Coroutine Image Loader) — کتابخانه‌ای برای بارگذاری تصاویر در Android است که کاملاً به زبان Kotlin نوشته شده و از کوروتین‌ها برای کار ناهمزمان استفاده می‌کند. این کتابخانه یک API یکپارچه برای بارگذاری تصاویر بیت‌مپ از شبکه، منابع، سیستم فایل و Content Provider با ذخیره‌سازی خودکار در چندین سطح ارائه می‌دهد.

برخلاف Glide و Picasso، Coil از Kotlin Coroutines به جای زنجیره callback استفاده می‌کند که کد را خطی‌تر و قابل پیش‌بینی‌تر می‌کند. تمام عملیات بارگذاری و رمزگشایی در رشته‌های پس‌زمینه از طریق Dispatchers.IO انجام می‌شود و نتیجه بدون جابجایی آشکار به رشته اصلی تحویل داده می‌شود.

Coil از تبدیل‌ها (Round، Blur، Grayscale)، انیمیشن‌های گذر، SVG و GIF و همچنین Target سفارشی برای نمایش غیراستاندارد پشتیبانی می‌کند. به گفته Google I/O 2023، Coil در آموزش‌های رسمی Jetpack Compose در کنار Glide توصیه شده است.

  • اندازه APK — حدود 150 KB (در مقابل 500 KB در Glide)
  • حداقل نسخه Android — API 21 (Lollipop)
  • وابستگی — Kotlin Coroutines (داخلی)

Coil چگونه کار می‌کند: ImageLoader و ImageRequest

ImageLoader — مؤلفه اصلی Coil است که مسئول اجرای درخواست‌های بارگذاری و مدیریت حافظه پنهان می‌باشد. هر نمونه شامل ارجاعاتی به MemoryCache، DiskCache، BitmapPool و استخر کوروتین‌ها است. به طور پیش‌فرض از Singleton ایجاد شده از طریق Coil.imageLoader(context) استفاده می‌شود.

ImageRequest

ImageRequest — شیئی است که یک درخواست بارگذاری تصویر را توصیف می‌کند: منبع داده (URL، URI، منبع Int)، ImageView یا Target مقصد، تبدیل‌ها، تنظیمات ذخیره‌سازی و placeholder. ImageRequest از طریق Builder ساخته می‌شود که انعطاف‌پذیری و خوانایی را فراهم می‌کند.

kotlin
val request = ImageRequest.Builder(context)
    .data("https://example.com/image.jpg")
    .crossfade(true)
    .size(512, 512)
    .transformations(listOf(RoundedCornersTransformation(12f)))
    .memoryCachePolicy(CachePolicy.ENABLED)
    .diskCachePolicy(CachePolicy.ENABLED)
    .target(imageView)
    .build()

پس از ساخته شدن، ImageRequest از طریق enqueue یا execute به ImageLoader منتقل می‌شود. متد enqueue یک کوروتین را راه‌اندازی می‌کند و Disposable برمی‌گرداند که امکان لغو بارگذاری در هنگام خروج از صفحه را فراهم می‌کند. متد execute یک تابع suspend است که مستقیماً Result برمی‌گرداند.

جریان اجرای درخواست

ImageLoader به ترتیب MemoryCache، DiskCache را بررسی می‌کند و فقط در صورت عدم وجود در هر دو، درخواست شبکه را از طریق HttpEngine انجام می‌دهد. پس از بارگذاری، بایت‌ها با در نظر گرفتن اندازه هدف به Bitmap رمزگشایی می‌شوند، تبدیل‌ها اعمال می‌شوند، نتیجه در هر دو حافظه پنهان ذخیره می‌شود و به Target منتقل می‌شود.

  • Memory Cache — ابتدا بررسی می‌شود، کلید — URL + پارامترها
  • Disk Cache — در صورت نبودن در حافظه بررسی می‌شود، کلید — MD5 URL
  • HttpEngine — به طور پیش‌فرض OkHttp، قابل سفارشی‌سازی از طریق مؤلفه

مؤلفه‌های اصلی Coil

Coil بر روی معماری مؤلفه‌ای با امکان تعویض هر بخش از طریق Dependency Injection ساخته شده است. تمام مؤلفه‌ها در ImageLoaderFactory ثبت می‌شوند و از طریق Builder به سازنده ImageLoader منتقل می‌شوند.

ImageLoader

ImageLoader — نقطه ورود برای تمام عملیات بارگذاری است. هر نمونه شامل استخر کوروتین‌ها، BitmapPool، MemoryCache، DiskCache و لیست interceptors است. به طور پیش‌فرض یک نمونه سراسری ایجاد می‌شود، اما برای تست ماژولار می‌توان نمونه‌های جداگانه با حافظه پنهان ایزوله ایجاد کرد.

MemoryCache

MemoryCache — حافظه پنهان درون‌حافظه‌ای مبتنی بر LRU (Least Recently Used) است که اشیاء Bitmap رمزگشایی شده را ذخیره می‌کند. حداکثر اندازه پیش‌فرض 25٪ از حافظه موجود برنامه است، اما نه کمتر از 32 MB. کلید حافظه پنهان از URL + اندازه + تبدیل‌ها تشکیل می‌شود که از ارائه تصویر نامعتبر جلوگیری می‌کند.

DiskCache

DiskCache — حافظه پنهان فایلی برای داده‌های خام (JPEG، PNG، WebP) و فراداده‌های رمزگشایی شده است. در دایرکتوری کش برنامه قرار دارد و پاکسازی خودکار را در هنگام تجاوز از حد مجاز پشتیبانی می‌کند. کار با دیسک از طریق DiskCache.Builder با تنظیم دایرکتوری و حداکثر اندازه انجام می‌شود.

سطوح ذخیره‌سازی در Coil

Coil یک استراتژی ذخیره‌سازی چندسطحی را پیاده‌سازی می‌کند که درخواست‌های شبکه را به حداقل می‌رساند و نمایش تصاویر را تسریع می‌بخشد. هر سطح هدف و عمر داده خاص خود را دارد.

سطحنوع ذخیره‌سازیعمراندازه پیش‌فرض
Memory CacheBitmap در حافظهتا جایگزینی LRU25٪ heap، از 32 MB
Disk Cacheفایل‌های JPEG/WebPتا تجاوز از حد مجاز250 MB
Http Cacheپاسخ‌های OkHttpبر اساس هدرهای Cache-Controlبستگی به کلاینت HTTP

Memory Cache دسترسی فوری به بیت‌مپ‌های رمزگشایی شده را فراهم می‌کند. Disk Cache کار برنامه را بدون شبکه (offline-first) پس از اولین بارگذاری تضمین می‌کند. Http Cache در سطح OkHttp درخواست‌های شرطی ETag و If-Modified-Since را پردازش می‌کند.

سیاست‌های ذخیره‌سازی در هر درخواست از طریق CachePolicy با سه مقدار پیکربندی می‌شوند: ENABLED، READ_ONLY، WRITE_ONLY، DISABLED. به عنوان مثال، برای آواتارهای کاربران می‌توان READ_ONLY را برای Memory Cache و ENABLED را برای Disk Cache تنظیم کرد.

نمونه‌های استفاده از Coil در Kotlin

Coil بسته به معماری برنامه چندین روش ادغام را ارائه می‌دهد. بیایید سه سناریوی کلیدی را با نمونه‌های کد عملی بررسی کنیم.

بارگذاری در ImageView از طریق extension

load — تابع extension برای ImageView، ساده‌ترین راه برای بارگذاری تصویر در یک خط. تابع URL، URI، منبع Int یا File و تمام پارامترهای اختیاری را از طریق پیکربندی‌کننده لامبدا می‌پذیرد.

kotlin
imageView.load("https://example.com/photo.jpg") {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    size(300, 300)
    transformations(CircleCropTransformation())
}

متد load یک Disposable برمی‌گرداند که می‌توان آن را در onDestroy یا هنگام استفاده مجدد از View لغو کرد. این کار از نشت حافظه و درخواست‌های شبکه اضافی در هنگام پیمایش سریع لیست جلوگیری می‌کند.

استفاده در Jetpack Compose

AsyncImage — تابع composable برای بارگذاری تصاویر در UI اعلانی. هر منبع داده و سه پارامتر اختیاری برای وضعیت‌ها را می‌پذیرد: placeholder، error و success.

kotlin
@Composable
fun NetworkImage(url: String) {
    AsyncImage(
        model = url,
        contentDescription = "تصویر شبکه",
        placeholder = ColorPainter(Color.Gray),
        error = ColorPainter(Color.Red)
    )
}

SubcomposeAsyncImage — نسخه انعطاف‌پذیرتر که امکان سفارشی‌سازی نمایش در حین بارگذاری را از طریق slot content فراهم می‌کند. این برای skeleton (shimmer) و نوار پیشرفت مفید است.

Target سفارشی برای خروجی غیراستاندارد

اگر ImageView یا AsyncImage مناسب نیستند، می‌توان Target را با یک متد onSuccess پیاده‌سازی کرد که Bitmap را می‌پذیرد. این برای بارگذاری در Notification، RemoteViews یا بافت OpenGL استفاده می‌شود.

kotlin
val target = object : BitmapTarget() {
    override fun onSuccess(result: Bitmap) {
        notificationRemoteView.setImageViewBitmap(R.id.icon, result)
    }
}

imageLoader.enqueue(
    ImageRequest.Builder(context)
        .data(url)
        .target(target)
        .build()
)

مقایسه Coil با کتابخانه‌های دیگر

انتخاب کتابخانه بارگذاری تصاویر به نیازهای پروژه بستگی دارد. Coil با Glide و Picasso رقابت می‌کند که هر کدام نقاط قوت خود را دارند. مقایسه ویژگی‌های اصلی در جدول ارائه شده است.

ویژگیCoilGlidePicasso
زبانKotlin (100%)Java + KotlinJava
اندازه APK~150 KB~500 KB~120 KB
کوروتین‌هاداخلیخیر (callback)خیر (callback)
Jetpack Composeپشتیبانی بومیاز طریق Accompanimentشخص ثالث
GIF/WebPبله (داخلی)بله (داخلی)خیر
توصیه Googleبله (I/O 2023)بلهخیر

برای پروژه‌های جدید در Kotlin و Jetpack Compose، Coil به دلیل وابستگی صفر اضافی به کوروتین‌ها و اندازه حداقلی به انتخاب طبیعی تبدیل می‌شود. Glide برای سناریوهای پیچیده با انیمیشن‌ها و پیش‌نمایش ویدیو ترجیح داده می‌شود. Picasso از هر دو از نظر عملکرد عقب‌تر است، اما در سادگی برنده می‌شود.

راه‌اندازی Coil در پروژه Android

اتصال Coil به پروژه Android از طریق وابستگی Gradle انجام می‌شود. پس از افزودن کتابخانه، به طور خودکار ImageLoader را از طریق ContentProvider ثبت می‌کند، بنابراین مقداردهی اولیه دستی در Application مورد نیاز نیست. در صورت نیاز به سفارشی‌سازی، ImageLoader خود از طریق Builder ایجاد می‌شود.

kotlin
// build.gradle.kts (ماژول برنامه)
dependencies {
    implementation("io.coil-kt:coil:2.6.0")
    // افزوده برای Jetpack Compose:
    implementation("io.coil-kt:coil-compose:2.6.0")
    // برای پشتیبانی SVG:
    implementation("io.coil-kt:coil-svg:2.6.0")
    // برای پشتیبانی GIF:
    implementation("io.coil-kt:coil-gif:2.6.0")
}

برای سفارشی‌سازی ImageLoader از ImageLoaderFactory استفاده می‌شود — Singleton ایجاد شده در Application.onCreate. در کارخانه می‌توان محدودیت‌های حافظه پنهان، کلاینت HTTP، رمزگشاهای سفارشی و ثبت رویداد را پیکربندی کرد. به طور پیش‌فرض Coil از OkHttp با استخر اتصال آماده استفاده می‌کند.

kotlin
class App : Application(), ImageLoaderFactory {
    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .memoryCache {
                MemoryCache.Builder()
                    .maxSizePercent(0.25)
                    .build()
            }
            .diskCache {
                DiskCache.Builder()
                    .directory(cacheDir.resolve("coil_cache"))
                    .maxSizeBytes(512 * 1024 * 1024)
                    .build()
            }
            .build()
    }
}

سؤالات متداول

Coil چیست و برای چه استفاده می‌شود؟

Coil — کتابخانه بارگذاری تصاویر در Android است که به زبان Kotlin با استفاده از کوروتین‌ها نوشته شده است. برای بارگذاری ناهمزمان، ذخیره‌سازی و نمایش تصاویر بیت‌مپ از شبکه، منابع یا سیستم فایل استفاده می‌شود.

Coil چه تفاوتی با Glide دارد؟

Coil 100٪ به زبان Kotlin نوشته شده است و به جای مکانیزم callback در Glide از کوروتین‌ها استفاده می‌کند. Coil اندازه APK کوچک‌تری دارد (~150 KB در مقابل ~500 KB) و پشتیبانی بومی از Jetpack Compose را از طریق AsyncImage فراهم می‌کند.

چگونه Coil را به پروژه Kotlin اضافه کنیم؟

وابستگی io.coil-kt:coil:2.6.0 را در build.gradle.kts اضافه کنید. برای Jetpack Compose همچنین io.coil-kt:coil-compose:2.6.0 را اضافه کنید. کتابخانه به طور خودکار ImageLoader را از طریق ContentProvider ثبت می‌کند.

Coil از چه نوع تصاویری پشتیبانی می‌کند؟

Coil از JPEG، PNG، WebP، BMP، SVG (از طریق ماژول coil-svg) و GIF (از طریق ماژول coil-gif) پشتیبانی می‌کند. فرمت‌های AVIF و HEIF از طریق رمزگشای سفارشی در دستگاه‌های دارای Android 10+ پشتیبانی می‌شوند.

چگونه حافظه پنهان را در Coil پیکربندی کنیم؟

حافظه پنهان از طریق ImageLoader.Builder پیکربندی می‌شود: memoryCache با مشخص کردن درصدی از heap، diskCache با مسیر و محدودیت به بایت. سیاست‌های حافظه پنهان (ENABLED، DISABLED، READ_ONLY) از طریق CachePolicy در هر درخواست پیکربندی می‌شوند.

خلاصه

  • Coil — کتابخانه بارگذاری تصاویر در Kotlin با پشتیبانی کامل از کوروتین‌ها و Jetpack Compose.
  • ImageLoader درخواست‌ها، ذخیره‌سازی و تبدیل‌ها را مدیریت می‌کند و از دو سطح حافظه پنهان استفاده می‌کند: Memory Cache و Disk Cache.
  • AsyncImage و SubcomposeAsyncImage ادغام با Compose را فراهم می‌کنند و از وضعیت‌های placeholder، error و success پشتیبانی می‌کنند.
  • اندازه APK ~150 KB Coil را به یکی از فشرده‌ترین کتابخانه‌های بارگذاری تصاویر در بازار تبدیل می‌کند.
  • تبدیل‌ها (RoundedCorners، CircleCrop، Blur) در کتابخانه تعبیه شده‌اند و با شتاب سخت‌افزاری کار می‌کنند.
  • Disk Cache دسترسی آفلاین به تصاویر بارگذاری شده قبلی را با محدودیت ذخیره‌سازی قابل تنظیم فراهم می‌کند.
  • Coil توسط Google توصیه شده است در راهنماهای رسمی Jetpack Compose که وضعیت آن را به عنوان یک استاندارد مدرن تأیید می‌کند.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید