本文为单张图片的内存缓存的示例
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>