Android图片加载 #

一、图片加载概述 #

Android图片加载涉及网络请求、内存缓存、磁盘缓存、图片解码、图片变换等多个环节,使用专业的图片加载库可以大大简化开发工作。

1.1 图片加载库对比 #

特性 Glide Coil
语言 Java Kotlin
协程支持 需要扩展 原生支持
体积 较大 较小
性能 优秀 优秀
API风格 Builder DSL

二、Glide #

2.1 添加依赖 #

kotlin
dependencies {
    implementation("com.github.bumptech.glide:glide:4.16.0")
    kapt("com.github.bumptech.glide:compiler:4.16.0")
}

2.2 基本使用 #

kotlin
// 简单加载
Glide.with(context)
    .load(url)
    .into(imageView)

// 加载资源图片
Glide.with(context)
    .load(R.drawable.image)
    .into(imageView)

// 加载本地文件
Glide.with(context)
    .load(File("/path/to/image.jpg"))
    .into(imageView)

2.3 占位图和错误图 #

kotlin
Glide.with(context)
    .load(url)
    .placeholder(R.drawable.placeholder)  // 加载中占位图
    .error(R.drawable.error)              // 加载失败图
    .fallback(R.drawable.fallback)        // URL为null时的图
    .into(imageView)

2.4 图片变换 #

kotlin
// 圆形图片
Glide.with(context)
    .load(url)
    .circleCrop()
    .into(imageView)

// 圆角图片
Glide.with(context)
    .load(url)
    .transform(CenterCrop(), RoundedCorners(16))
    .into(imageView)

// 自定义变换
Glide.with(context)
    .load(url)
    .transform(BlurTransformation(context, 25))
    .into(imageView)

2.5 缓存策略 #

kotlin
Glide.with(context)
    .load(url)
    .diskCacheStrategy(DiskCacheStrategy.ALL)      // 缓存原图和变换后的图
    .diskCacheStrategy(DiskCacheStrategy.NONE)     // 不缓存
    .diskCacheStrategy(DiskCacheStrategy.DATA)     // 只缓存原图
    .diskCacheStrategy(DiskCacheStrategy.RESOURCE) // 只缓存变换后的图
    .skipMemoryCache(true)                         // 跳过内存缓存
    .into(imageView)

2.6 加载回调 #

kotlin
Glide.with(context)
    .load(url)
    .listener(object : RequestListener<Drawable> {
        override fun onLoadFailed(
            e: GlideException?,
            model: Any?,
            target: Target<Drawable>,
            isFirstResource: Boolean
        ): Boolean {
            Log.e("Glide", "Load failed", e)
            return false
        }
        
        override fun onResourceReady(
            resource: Drawable,
            model: Any,
            target: Target<Drawable>?,
            dataSource: DataSource,
            isFirstResource: Boolean
        ): Boolean {
            Log.d("Glide", "Load success")
            return false
        }
    })
    .into(imageView)

2.7 预加载 #

kotlin
// 预加载图片到缓存
Glide.with(context)
    .load(url)
    .preload()

// 下载图片
Glide.with(context)
    .download(url)
    .submit()

2.8 清除缓存 #

kotlin
// 清除内存缓存(在主线程)
Glide.get(context).clearMemory()

// 清除磁盘缓存(在子线程)
Thread {
    Glide.get(context).clearDiskCache()
}.start()

三、Coil #

3.1 添加依赖 #

kotlin
dependencies {
    implementation("io.coil-kt:coil:2.5.0")
}

3.2 基本使用 #

kotlin
// 简单加载
imageView.load(url)

// 带配置加载
imageView.load(url) {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    error(R.drawable.error)
    transformations(CircleCropTransformation())
}

// 加载资源图片
imageView.load(R.drawable.image)

// 加载本地文件
imageView.load(File("/path/to/image.jpg"))

3.3 图片变换 #

kotlin
// 圆形图片
imageView.load(url) {
    transformations(CircleCropTransformation())
}

// 圆角图片
imageView.load(url) {
    transformations(RoundedCornersTransformation(16f))
}

// 高斯模糊
imageView.load(url) {
    transformations(BlurTransformation(context, 25f))
}

// 组合变换
imageView.load(url) {
    transformations(
        CircleCropTransformation(),
        GrayscaleTransformation()
    )
}

3.4 加载回调 #

kotlin
imageView.load(url) {
    listener(
        onStart = {
            Log.d("Coil", "Load started")
        },
        onSuccess = { _, _ ->
            Log.d("Coil", "Load success")
        },
        onError = { _, _ ->
            Log.e("Coil", "Load error")
        }
    )
}

3.5 获取Bitmap #

kotlin
val imageLoader = context.imageLoader
val request = ImageRequest.Builder(context)
    .data(url)
    .target { drawable ->
        val bitmap = (drawable as BitmapDrawable).bitmap
        // 使用bitmap
    }
    .build()

imageLoader.enqueue(request)

// 或使用协程
val bitmap = context.imageLoader.execute(
    ImageRequest.Builder(context)
        .data(url)
        .build()
).drawable?.toBitmap()

3.6 自定义ImageLoader #

kotlin
val imageLoader = ImageLoader.Builder(context)
    .crossfade(true)
    .okHttpClient {
        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .build()
    }
    .memoryCache {
        MemoryCache.Builder(context)
            .maxSizePercent(0.25)
            .build()
    }
    .diskCache {
        DiskCache.Builder()
            .directory(context.cacheDir.resolve("image_cache"))
            .maxSizeBytes(100 * 1024 * 1024)  // 100MB
            .build()
    }
    .build()

Coil.setImageLoader(imageLoader)

3.7 在Application中配置 #

kotlin
class MyApp : Application(), ImageLoaderFactory {
    
    override fun newImageLoader(): ImageLoader {
        return ImageLoader.Builder(this)
            .crossfade(true)
            .okHttpClient {
                OkHttpClient.Builder()
                    .addInterceptor(HttpLoggingInterceptor().apply {
                        level = HttpLoggingInterceptor.Level.BASIC
                    })
                    .build()
            }
            .build()
    }
}

四、RecyclerView图片加载 #

4.1 Glide在RecyclerView中使用 #

kotlin
class UserAdapter : RecyclerView.Adapter<UserViewHolder>() {
    
    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = users[position]
        
        Glide.with(holder.itemView.context)
            .load(user.avatar)
            .placeholder(R.drawable.avatar_placeholder)
            .circleCrop()
            .into(holder.avatarView)
    }
}

4.2 Coil在RecyclerView中使用 #

kotlin
class UserAdapter : RecyclerView.Adapter<UserViewHolder>() {
    
    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = users[position]
        
        holder.avatarView.load(user.avatar) {
            placeholder(R.drawable.avatar_placeholder)
            transformations(CircleCropTransformation())
        }
    }
}

五、图片加载最佳实践 #

5.1 使用合适的图片尺寸 #

kotlin
// Glide指定尺寸
Glide.with(context)
    .load(url)
    .override(200, 200)
    .into(imageView)

// Coil指定尺寸
imageView.load(url) {
    size(200, 200)
}

5.2 使用缩略图 #

kotlin
// Glide缩略图
Glide.with(context)
    .load(url)
    .thumbnail(
        Glide.with(context)
            .load(thumbnailUrl)
            .override(100, 100)
    )
    .into(imageView)

5.3 取消请求 #

kotlin
// Glide取消请求
Glide.with(context).clear(imageView)

// Coil自动取消(在View detach时)
// 或手动取消
val disposable = imageView.load(url)
disposable.dispose()

5.4 内存优化 #

kotlin
// 使用RGB_565格式减少内存
Glide.with(context)
    .load(url)
    .format(DecodeFormat.PREFER_RGB_565)
    .into(imageView)

// Coil
imageView.load(url) {
    bitmapConfig(Bitmap.Config.RGB_565)
}

六、总结 #

本章详细介绍了Android图片加载:

  1. 图片加载库的选择
  2. Glide的使用方法
  3. Coil的使用方法
  4. RecyclerView中的图片加载
  5. 最佳实践

选择合适的图片加载库并正确使用,可以有效提升应用的性能和用户体验。

最后更新:2026-03-26