Android Coil ImageLoader MemoryCache设置Key与复用内存缓存,Kotlin

[复制链接]
发表于 2025-10-29 03:57:56 | 显示全部楼层 |阅读模式
Android Coil ImageLoader MemoryCache设置Key与复用内存缓存,Kotlin

 

 
  1. import android.content.ContentUris
  2. import android.content.Context
  3. import android.net.Uri
  4. import android.os.Bundle
  5. import android.provider.MediaStore
  6. import android.util.Log
  7. import androidx.appcompat.app.AppCompatActivity
  8. import androidx.lifecycle.lifecycleScope
  9. import androidx.recyclerview.widget.GridLayoutManager
  10. import androidx.recyclerview.widget.LinearLayoutManager
  11. import androidx.recyclerview.widget.RecyclerView
  12. import kotlinx.coroutines.Dispatchers
  13. import kotlinx.coroutines.launch
  14. class MainActivity : AppCompatActivity() {
  15.     companion object {
  16.         const val TAG = "fly"
  17.         const val SPAN_COUNT = 8
  18.     }
  19.     override fun onCreate(savedInstanceState: Bundle?) {
  20.         super.onCreate(savedInstanceState)
  21.         setContentView(R.layout.rv_layout)
  22.         val rv = findViewById<RecyclerView>(R.id.rv)
  23.         val layoutManager = GridLayoutManager(this, SPAN_COUNT)
  24.         layoutManager.orientation = LinearLayoutManager.VERTICAL
  25.         val adapter = ImageAdapter(this, 0)
  26.         rv.adapter = adapter
  27.         rv.layoutManager = layoutManager
  28.         //rv.setHasFixedSize(true)
  29.         //rv.setItemViewCacheSize(SPAN_COUNT * 20)
  30.         //rv.recycledViewPool.setMaxRecycledViews(0, SPAN_COUNT * 20)
  31.         val ctx = this
  32.         lifecycleScope.launch(Dispatchers.IO) {
  33.             val lists = readAllImage(ctx)
  34.             Log.d(TAG, "readAllImage size=${lists.size}")
  35.             lifecycleScope.launch(Dispatchers.Main) {
  36.                 adapter.dataChanged(lists)
  37.             }
  38.         }
  39.     }
  40.     class MyData(var path: String, var uri: Uri)
  41.     private fun readAllImage(ctx: Context): ArrayList<MyData> {
  42.         val photos = ArrayList<MyData>()
  43.         //读取所有图
  44.         val cursor = ctx.contentResolver.query(
  45.             MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null
  46.         )
  47.         while (cursor!!.moveToNext()) {
  48.             //路径
  49.             val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
  50.             val id = cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID)
  51.             val imageUri: Uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor.getLong(id))
  52.             //名称
  53.             //val name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME))
  54.             //大小
  55.             //val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE))
  56.             photos.add(MyData(path, imageUri))
  57.         }
  58.         cursor.close()
  59.         return photos
  60.     }
  61. }
复制代码
 
 
  1. import android.content.Context
  2. import android.graphics.Bitmap
  3. import android.util.Log
  4. import android.view.View
  5. import android.view.ViewGroup
  6. import androidx.appcompat.widget.AppCompatImageView
  7. import androidx.lifecycle.lifecycleScope
  8. import androidx.recyclerview.widget.RecyclerView
  9. import coil.ImageLoader
  10. import coil.memory.MemoryCache
  11. import coil.request.CachePolicy
  12. import coil.request.ImageRequest
  13. import kotlinx.coroutines.Dispatchers
  14. import kotlinx.coroutines.launch
  15. class ImageAdapter : RecyclerView.Adapter<ImageHolder> {
  16.     private var mCtx: Context? = null
  17.     private var mImageLoader: ImageLoader? = null
  18.     private var mViewSize = 0
  19.     constructor(ctx: Context, type: Int) : super() {
  20.         mCtx = ctx
  21.         mImageLoader = ImageLoader.Builder(mCtx!!)
  22.             .memoryCachePolicy(CachePolicy.ENABLED)
  23.             .availableMemoryPercentage(0.9999)
  24.             .bitmapPoolingEnabled(true)
  25.             .bitmapConfig(Bitmap.Config.RGB_565)
  26.             .diskCachePolicy(CachePolicy.ENABLED)
  27.             .build()
  28.         Log.d(MainActivity.TAG, "memoryCache.maxSize=${mImageLoader?.memoryCache?.maxSize}")
  29.         mViewSize = mCtx!!.resources.displayMetrics.widthPixels / MainActivity.SPAN_COUNT
  30.     }
  31.     private var mItems = ArrayList<MainActivity.MyData>()
  32.     fun dataChanged(items: ArrayList<MainActivity.MyData>) {
  33.         this.mItems = items
  34.         notifyDataSetChanged()
  35.     }
  36.     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageHolder {
  37.         val view = MyIV(mCtx!!, mViewSize)
  38.         return ImageHolder(view)
  39.     }
  40.     override fun getItemCount(): Int {
  41.         return mItems.size
  42.     }
  43.     override fun onBindViewHolder(holder: ImageHolder, position: Int) {
  44.         bind(mItems[position], holder.image)
  45.     }
  46.     private fun bind(data: MainActivity.MyData, image: MyIV) {
  47.         val key = MemoryCache.Key.invoke(data.path)
  48.         val bmp = mImageLoader?.memoryCache?.get(key)
  49.         if (bmp != null && bmp.byteCount > 0) {
  50.             Log.d(
  51.                 MainActivity.TAG,
  52.                 "memory cache bmp=${bmp.byteCount} ${mImageLoader?.memoryCache?.size}/${mImageLoader?.memoryCache?.maxSize}"
  53.             )
  54.             image.setImageBitmap(bmp)
  55.         } else {
  56.             val t = System.currentTimeMillis()
  57.             val request = ImageRequest.Builder(mCtx!!)
  58.                 .data(data.uri)
  59.                 .size(mViewSize)
  60.                 .target(image)
  61.                 .memoryCacheKey(key)
  62.                 .build()
  63.             (mCtx as? MainActivity)?.lifecycleScope?.launch(Dispatchers.IO) {
  64.                 mImageLoader?.execute(request)
  65.             }
  66.             Log.d(MainActivity.TAG, "no memory cache time=${System.currentTimeMillis() - t}")
  67.         }
  68.     }
  69. }
  70. class ImageHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
  71.     var image = itemView as MyIV
  72. }
  73. class MyIV : AppCompatImageView {
  74.     private var mSize = 0
  75.     constructor(ctx: Context, size: Int) : super(ctx) {
  76.         mSize = size
  77.         scaleType = ScaleType.CENTER_CROP
  78.     }
  79.     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  80.         super.onMeasure(widthMeasureSpec, heightMeasureSpec)
  81.         setMeasuredDimension(mSize, mSize)
  82.     }
  83. }
复制代码
 
 
1、已知标题,发现Coil在宫格多时间,如果直接:
  1. mImageLoader?.enqueue(request)
复制代码
也有肯定小的耗时。以是干脆用协程包装起来。
 
2、固然通过设置内存系数
  1. availableMemoryPercentage
复制代码
扩大了内存,但跑起来发现设置后内存照旧比力小(约300mb),这是不敷的,必要通过其他设置方式扩大内存空间。
 
3、app跑起来后,没有在当前app的硬盘缓存空间发现图片解码后的磁盘文件缓存陈迹。这必要再设置。
 
 
 
 
 
Android图片加载框架Coil,Kotlin-CSDN博客文章欣赏阅读649次。Coil是专门针对Android平台上的Kotlin语言特性操持,这不像Glide,Glide的焦点框架语言是Java。Coil实现看更细颗粒度的内存、磁盘缓存的客制化设置。
https://blog.csdn.net/zhangphil/article/details/145558324
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表