You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Coil配合WebView实现图片缓存及返回WebResourceResponse

Coil实现WebView图片缓存并返回WebResourceResponse方案

核心结论

Coil完全支持WebView图片缓存,默认已启用内存+磁盘缓存,只需在shouldInterceptRequest中通过同步方式获取Coil的图片数据即可解决你的问题。

解决方案

由于Coil的execute是挂起函数,无法直接在shouldInterceptRequest这个同步方法中调用,我们可以用runBlocking包裹挂起调用,实现同步获取图片结果。同时优化ImageRequest配置,直接请求Bitmap以提升效率。

完整实现代码

override fun shouldInterceptRequest(
    view: WebView?,
    request: WebResourceRequest?
): WebResourceResponse? {
    try {
        val url = request?.url?.toString() ?: return super.shouldInterceptRequest(view, request)
        val imageType = when {
            url.lowercase().contains(".jpg") || url.lowercase().contains(".jpeg") -> "image/jpeg" to Bitmap.CompressFormat.JPEG
            url.lowercase().contains(".png") -> "image/png" to Bitmap.CompressFormat.PNG // 修正原代码中PNG类型错误
            else -> return super.shouldInterceptRequest(view, request)
        }

        // 构建Coil的Bitmap请求,启用缓存
        val imageRequest = ImageRequest.Builder(view?.context ?: requireContext())
            .data(url)
            .memoryCachePolicy(CachePolicy.ENABLED) // 启用内存缓存
            .diskCachePolicy(CachePolicy.ENABLED)   // 启用磁盘缓存
            .target { } // 空target,仅用于获取Bitmap
            .build()

        // 用runBlocking同步获取Bitmap
        val result = runBlocking {
            view?.context?.imageLoader?.execute(imageRequest)
        }

        val bitmap = result?.drawable?.toBitmap() ?: return super.shouldInterceptRequest(view, request)
        return WebResourceResponse(
            imageType.first,
            "UTF-8",
            getBitmapInputStream(bitmap, imageType.second)
        )
    } catch (e: Exception) {
        e.printStackTrace()
        return super.shouldInterceptRequest(view, request)
    }
}

private fun getBitmapInputStream(bitmap: Bitmap, compressFormat: Bitmap.CompressFormat): InputStream {
    val byteArrayOutputStream = ByteArrayOutputStream()
    bitmap.compress(compressFormat, 80, byteArrayOutputStream)
    val bitmapData = byteArrayOutputStream.toByteArray()
    return ByteArrayInputStream(bitmapData)
}

关键细节说明

  • 同步获取结果:使用runBlocking将挂起的execute调用转为同步执行,适配shouldInterceptRequest的同步要求。WebView的拦截请求本身在后台线程处理,不会阻塞UI主线程。
  • 缓存配置:显式设置memoryCachePolicy和diskCachePolicy为ENABLED,确保Coil优先读取缓存,和Glide的DiskCacheStrategy.ALL效果一致。
  • 类型修正:原代码中PNG图片返回的MIME类型错误为image/jpg,修正为image/png以符合标准。
  • 异常处理:保留原有的异常捕获逻辑,确保请求失败时WebView能正常加载图片。

额外优化建议

  • 可以给Coil的ImageRequest添加size限制,比如设置为WebView的可见尺寸或Size.ORIGINAL,减少内存占用。
  • 复用全局ImageLoader实例,避免重复创建资源消耗。

内容的提问来源于stack exchange,提问作者Rakshit Nawani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:08:10