Coil — คืออะไร แนวคิดหลัก และ ImageLoader ใน Android

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-05 เวลาอ่าน: 9 นาที

Coil เป็นไลบรารีสำหรับโหลดรูปภาพบน Android ที่เขียนด้วย Kotlin และสร้างบน coroutines ตาม เอกสารทางการ ไลบรารีรองรับ Memory Cache, Disk Cache และการแปลงด้วยการเร่งฮาร์ดแวร์ Coil โดดเด่นด้วยขนาด APK ที่เล็กที่สุด (ประมาณ 150 KB) และความเข้ากันได้อย่างสมบูรณ์กับ Jetpack Compose

ประเด็นสำคัญ

  • Coil เป็นไลบรารีสำหรับโหลดรูปภาพบน Android ที่ใช้ Kotlin Coroutines และ Kotlin Serialization
  • ImageLoader เป็น component หลักที่จัดการคำขอ การแคช และการแปลงรูปภาพ
  • Memory Cache เก็บรูปภาพบิตแมปที่ถอดรหัสแล้วใน RAM เพื่อการเข้าถึงทันที
  • Disk Cache บันทึกไฟล์ที่บีบอัดบนพื้นที่จัดเก็บเพื่อการทำงานแบบออฟไลน์และลดปริมาณการรับส่งข้อมูล
  • Jetpack Compose — ไลบรารีรองรับ AsyncImage และ SubcomposeAsyncImage สำหรับ UI แบบประกาศ

Coil คืออะไร?

Coil (Coroutine Image Loader) เป็นไลบรารีสำหรับโหลดรูปภาพบน Android ที่เขียนด้วย Kotlin ทั้งหมดและใช้ coroutines สำหรับการดำเนินการแบบอะซิงโครนัส โดยมี API แบบรวมสำหรับโหลดรูปภาพบิตแมปจากเครือข่าย ทรัพยากร ระบบไฟล์ และ Content Provider พร้อมการแคชอัตโนมัติหลายระดับ

แตกต่างจาก Glide และ Picasso ตรงที่ Coil ใช้ Kotlin Coroutines แทนการเรียกกลับแบบลูกโซ่ ทำให้โค้ดเป็นเชิงเส้นและคาดการณ์ได้มากขึ้น การดำเนินการโหลดและถอดรหัสทั้งหมดทำงานบนเธรดพื้นหลังผ่าน dispatcher 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 และพูล coroutines โดยค่าเริ่มต้น จะใช้ซิงเกิลตันที่สร้างผ่าน 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 จะถูกส่งไปยัง ImageLoader ผ่าน enqueue หรือ execute เมธอด enqueue เริ่ม coroutine และส่งคืน Disposable ซึ่งอนุญาตให้ยกเลิกการโหลดเมื่อออกจากหน้าจอ เมธอด execute เป็นฟังก์ชัน suspend ที่ส่งคืน Result โดยตรง

ขั้นตอนการดำเนินการขอ

ImageLoader ตรวจสอบ MemoryCache, DiskCache ตามลำดับ และเมื่อทั้งสองไม่พบข้อมูลจะดำเนินการขอเครือข่ายผ่าน HttpEngine หลังจากการโหลด ไบต์จะถูกถอดรหัสเป็น Bitmap โดยพิจารณาขนาดเป้าหมาย ใช้การแปลง ผลลัพธ์จะถูกเก็บในแคชทั้งสองและส่งต่อไปยัง Target

  • Memory Cache — ตรวจสอบก่อน คีย์คือ URL + พารามิเตอร์
  • Disk Cache — ตรวจสอบเมื่อไม่พบในหน่วยความจำ คีย์คือ MD5 ของ URL
  • HttpEngine — OkHttp โดยค่าเริ่มต้น ปรับแต่งได้ผ่าน component

ส่วนประกอบหลักของ Coil

Coil สร้างบนสถาปัตยกรรมแบบ component ที่สามารถเปลี่ยนส่วนใดๆ ได้ผ่าน Dependency Injection component ทั้งหมดลงทะเบียนใน ImageLoaderFactory และส่งไปยังคอนสตรักเตอร์ของ ImageLoader ผ่าน builder

ImageLoader

ImageLoader เป็นจุดเริ่มต้นสำหรับการดำเนินการโหลดทั้งหมด แต่ละอินสแตนซ์ประกอบด้วยพูล coroutines, BitmapPool, MemoryCache, DiskCache และรายการตัวสกัดกั้น โดยค่าเริ่มต้น จะสร้างอินสแตนซ์ส่วนกลางหนึ่งอัน แต่สำหรับการทดสอบหน่วย สามารถสร้างอินสแตนซ์แยกกับแคชที่แยกได้

MemoryCache

MemoryCache เป็นแคชในหน่วยความจำแบบ LRU (Least Recently Used) ที่เก็บออบเจกต์ Bitmap ที่ถอดรหัสแล้ว ขนาดสูงสุดโดยค่าเริ่มต้นคือ 25% ของหน่วยความจำที่มีของแอปพลิเคชัน แต่ไม่น้อยกว่า 32 MB คีย์แคชสร้างจาก URL + ขนาด + การแปลง ซึ่งป้องกันการดึงรูปภาพที่ล้าสมัย

DiskCache

DiskCache เป็นแคชแบบไฟล์สำหรับข้อมูลดิบ (JPEG, PNG, WebP) และเมตาดาต้าที่ถอดรหัสแล้ว อยู่ในไดเรกทอรีแคชของแอปพลิเคชันและรองรับการล้างอัตโนมัติเมื่อเกินขีดจำกัด การดำเนินการดิสก์ทำผ่าน DiskCache.Builder พร้อมการกำหนดค่าไดเรกทอรีและขนาดสูงสุด

ระดับการแคชใน Coil

Coil ใช้กลยุทธ์การแคชหลายระดับที่ลดคำขอเครือข่ายและเร่งการแสดงรูปภาพ แต่ละระดับมีวัตถุประสงค์และอายุข้อมูลของตัวเอง

ระดับประเภทการจัดเก็บอายุขนาดเริ่มต้น
Memory CacheBitmap ใน RAMจนกว่าจะถูก LRU แทนที่25% ของ heap จาก 32 MB
Disk Cacheไฟล์ JPEG/WebPจนเกินขีดจำกัด250 MB
Http Cacheการตอบสนอง OkHttpตามหัวเรื่อง Cache-Controlขึ้นอยู่กับ HTTP client

Memory Cache ให้การเข้าถึง Bitmap ที่ถอดรหัสแล้วทันที 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 ผ่านส่วนขยาย

load เป็นฟังก์ชันส่วนขยายสำหรับ ImageView วิธีที่ง่ายที่สุดในการโหลดรูปภาพในบรรทัดเดียว ฟังก์ชันรับ URL, URI, ทรัพยากร Int หรือ File พร้อมพารามิเตอร์เพิ่มเติมทั้งหมดผ่านตัวกำหนดค่า lambda

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 เป็นเวอร์ชันที่ยืดหยุ่นกว่าซึ่งอนุญาตให้ปรับแต่งการแสดงผลระหว่างการโหลดผ่านช่องเนื้อหา มีประโยชน์สำหรับโครงกระดูก (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
Coroutinesในตัวไม่มี (callback)ไม่มี (callback)
Jetpack Composeรองรับโดยตรงผ่าน accompanistบุคคลที่สาม
GIF/WebPใช่ (ในตัว)ใช่ (ในตัว)ไม่
คำแนะนำจาก Googleใช่ (I/O 2023)ใช่ไม่

สำหรับโปรเจกต์ใหม่บน Kotlin และ Jetpack Compose Coil กลายเป็นตัวเลือกโดยธรรมชาติเนื่องจากการไม่พึ่งพา coroutines เพิ่มเติมและขนาดที่เล็กที่สุด Glide ยังคงเป็นที่นิยมสำหรับสถานการณ์ที่ซับซ้อนด้วยแอนิเมชันและตัวอย่างวิดีโอ Picasso ด้อยกว่าทั้งสองในด้านฟังก์ชันการทำงาน แต่ชนะในด้านความเรียบง่าย

การตั้งค่า Coil ในโปรเจกต์ Android

การเพิ่ม Coil ในโปรเจกต์ Android ทำผ่านการพึ่งพา Gradle หลังจากเพิ่ม ไลบรารีจะลงทะเบียน ImageLoader โดยอัตโนมัติผ่าน ContentProvider ดังนั้นไม่จำเป็นต้องเริ่มต้นด้วยตนเองใน Application หากต้องการปรับแต่ง จะสร้าง ImageLoader ที่กำหนดเองผ่าน builder

kotlin
// build.gradle.kts (app module)
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 — ซิงเกิลตันที่สร้างใน Application.onCreate ในโรงงาน คุณสามารถกำหนดค่าขีดจำกัดแคช, HTTP client, ตัวถอดรหัสที่กำหนดเอง และการบันทึก โดยค่าเริ่มต้น 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 โดยใช้ coroutines ใช้สำหรับโหลด แคช และแสดงรูปภาพบิตแมปแบบอะซิงโครนัสจากเครือข่าย ทรัพยากร หรือระบบไฟล์

Coil แตกต่างจาก Glide อย่างไร?

Coil เขียนด้วย Kotlin 100% และใช้ coroutines แทนกลไก 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 ที่รองรับ coroutines และ 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 สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม