缓存的使用之单张图片 + LruCache

本文为单张图片的内存缓存的示例

1、首先创建LruCache缓存工具类, 拿出最大可用内存的八分之一,作为图片缓存的大小。

/**
 * 图片的内存缓存工具类
 */
class CacheUtils {

    companion object{

        lateinit var mMemoryCache : LruCache<String, Bitmap>
        private var  maxMemory by Delegates.notNull<Int>()
        private var  cacheSize by Delegates.notNull<Int>()

        fun  initCacheAbout(){
            // 获得虚拟机能提供的最大内存,超过这个大小会抛出OutOfMemory的异常
            maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
            cacheSize = maxMemory / 8
            mMemoryCache = ImageCache(cacheSize)
        }

        fun addBitmapToMemoryCache(key: String?, bitmap: Bitmap?) {
            if (getBitmapFromMemCache(key) == null) {
                Log.d("Neo","addBitmapToMemoryCache(存之前),长度="+mMemoryCache.size())
                mMemoryCache.put(key, bitmap)
                Log.d("Neo","addBitmapToMemoryCache(存完之后),长度="+mMemoryCache.size())
            }
        }

        fun getBitmapFromMemCache(key: String?): Bitmap? {
            Log.d("Neo","getBitmapFromMemCache() temp=$mMemoryCache")
            Log.d("Neo","getBitmapFromMemCache() 长度="+mMemoryCache.size())
            Log.d("Neo","getBitmapFromMemCache() temp[key]="+mMemoryCache[key])
            return mMemoryCache[key]
        }

        class ImageCache(cacheSize: Int) : LruCache<String, Bitmap>(cacheSize) {
            override fun sizeOf(key: String?, value: Bitmap?): Int {
                return value!!.byteCount / 1024
            }
        }
    }
}

2、创建图片下载工具类

public class BitmapUtil {

    /**
     * HttpURLConnection下载图片并转化为bitmap
     * @param imgUrl
     * @return
     */
    public static Bitmap getBitmapFromNet(String imgUrl) {
        try {
            //生成url
            URL url = new URL(imgUrl);
            //建立连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            //设置超时 5s
            connection.setConnectTimeout(5000);
            //设置请求方法
            connection.setRequestMethod("GET");
            //连接成功
            if (connection.getResponseCode()==200){
                //获取输入流
                InputStream in=connection.getInputStream();
                //将流转化为bitmap
                return BitmapFactory.decodeStream(in);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

3、使用LruCache。

  • 首先判断内存里是否有图片缓存,如果有直接显示;
  • 如果没有,则需要通过HttpURLConnection下载,如果下载成功则将图片存入缓存,下载失败则存入一张默认图片;
  • 然后读取缓存,将图片显示出来;
/**
 * 【单张图片内存缓存】
 *
 * 杀进程或者清空APP缓存, 缓存数据就不存在了
 */
class SingleImageMemoryCacheActivity : AppCompatActivity() {

    lateinit var imageView : ImageView
    private val oriUrl : String = "https://t7.baidu.com/it/u=2168645659,3174029352&fm=193&f=GIF"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_single_image_memory_cache)
        imageView = findViewById(R.id.image_id)
        loadBitmap(oriUrl,imageView)
    }

    private fun loadBitmap(resId: String?, imageView: ImageView?) {
        // 查看下内存缓存中是否缓存了这张图片
        val bitmap = CacheUtils.getBitmapFromMemCache(resId)
        if (bitmap != null) {
            Log.d("Neo","取到指定图片的缓存了,直接展示")
            imageView?.setImageBitmap(bitmap)
        } else {
            Log.d("Neo","没有取到指定图片的缓存,进行下一步")
            imageView?.setImageResource(R.drawable.ic_launcher_background)
            val task = BitmapWorkerTask(this@SingleImageMemoryCacheActivity)
            task.execute(resId)
        }
    }

    companion object {
        class BitmapWorkerTask internal constructor(context : SingleImageMemoryCacheActivity) : AsyncTask<String,String,Bitmap>(){

            private val activityReference: WeakReference<SingleImageMemoryCacheActivity> = WeakReference(context)
            private lateinit var thisUrl : String

            override fun doInBackground(vararg params: String?): Bitmap {
                val thisActivity = activityReference.get()
                //网络图片请求失败,则加载本地的默认图片,同时缓存这张默认图片
                return if(BitmapUtil.getBitmapFromNet(params[0]) == null){
                    Log.d("Neo","网图获取失败,提供一张本地图片")
                    thisUrl = "LOCAL_IMAGE_RESOURCE"
                    BitmapFactory.decodeResource(thisActivity?.resources, R.mipmap.icon6)
                }else{
                    Log.d("Neo","网图获取成功并返回")
                    thisUrl = params[0].toString()
                    BitmapUtil.getBitmapFromNet(params[0])
                }
            }

            override fun onPostExecute(result: Bitmap?) {
                val thisActivity = activityReference.get()
                Log.d("Neo","展示图片,并将图片保存到内存缓存中")
                thisActivity?.imageView?.setImageBitmap(result)
                CacheUtils.addBitmapToMemoryCache(thisUrl, result)
            }
        }
    }
}

4、布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activitys.SingleImageMemoryCacheActivity">

    <ImageView
        android:id="@+id/image_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容