首页 > 其他分享 >ListView 加载图片实现三级缓存效果

ListView 加载图片实现三级缓存效果

时间:2022-12-14 19:37:51浏览次数:56  
标签:缓存 String bitmap imagePath import imageView ListView 加载


import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

/*
String iamgePath = http://127.0.1:8080//L05_Web/images/f10.jpg和ImageView对象
1). 根据url从一级缓存中取对应的bitmap对象
如果有, 显示(结束)
如果没有, 进入2)
2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象
如果有: 显示, 缓存到一级缓存中(结束)
如果没有, 进入3)
3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象
如果没有: 显示提示错误的图片(结束)
如果有:
显示
缓存到一级缓存
缓存到二级缓存
*/
public class ImageLoader {

private Context context;
private int loadingImageRes;
private int errorImageRes;

public ImageLoader(Context context, int loadingImageRes, int errorImageRes) {
super();
this.context = context;
this.loadingImageRes = loadingImageRes;
this.errorImageRes = errorImageRes;
}

//用于缓存bitmap的容器对象
private Map<String, Bitmap> cacheMap = new HashMap<String, Bitmap>();

/**
* 加载图片并显示
* @param imagePath
* @param imageView
*/
public void loadImage(String imagePath, ImageView imageView) {

//将需要显示的图片url保存到视图上
imageView.setTag(imagePath);

/*
1). 根据url从一级缓存中取对应的bitmap对象
如果有, 显示(结束)
如果没有, 进入2)
*/
Bitmap bitmap = getFromFirstCache(imagePath);
if(bitmap!=null) {
imageView.setImageBitmap(bitmap);
return;
}
/*
2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象
如果有: 显示, 缓存到一级缓存中(结束)
如果没有, 进入3)

/storage/sdcard/Android/data/packageName/files/图片文件名(xxx.jpg)
*/
bitmap = getFromSecondCache(imagePath);
if(bitmap!=null) {
imageView.setImageBitmap(bitmap);
cacheMap.put(imagePath, bitmap);
return;
}

/*
3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象
如果没有: 显示提示错误的图片(结束)
如果有:
缓存到一级缓存(分线程)
缓存到二级缓存(分线程)
显示(主线程)

*/

loadBitmapFromThirdCache(imagePath, imageView);
}

/**
* 根据图片url从三级缓存中取对应的bitmap对象并显示
* @param imagePath
* @param imageView
* AsyncTask
* loadBitmapFromThirdCache("../b.jpg", imageView)
* loadBitmapFromThirdCache("../f.jpg", imageView)--->imageView.setTag("../f.jpg")
*/
private void loadBitmapFromThirdCache(final String imagePath, final ImageView imageView) {
new AsyncTask<Void, Void, Bitmap>() {
protected void onPreExecute() {
imageView.setImageResource(loadingImageRes);
}

//联网请求得到bitmap对象
@Override
protected Bitmap doInBackground(Void... params) {
//在分线程执行, 可能需要等待一定时间才会执行
//在等待的过程中imageView中的tag值就有可能改变了
//如果改变了, 就不应该再去加载图片(此图片此时不需要显示)

Bitmap bitmap = null;
try {

//在准备请求服务器图片之前, 判断是否需要加载
String newImagePath = (String) imageView.getTag();
if(newImagePath!=imagePath) {//视图已经被复用了
return null;
}

//得到连接
URL url = new URL(imagePath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
//连接
connection.connect();
//发请求读取返回的数据并封装为bitmap
int responseCode = connection.getResponseCode();
if(responseCode==200) {
InputStream is = connection.getInputStream();//图片文件流
//将is封装为bitmap
bitmap = BitmapFactory.decodeStream(is);
is.close();

if(bitmap!=null) {
//缓存到一级缓存(分线程)
cacheMap.put(imagePath, bitmap);
//缓存到二级缓存(分线程)
// /storage/sdcard/Android/data/packageName/files/
String filesPath = context.getExternalFilesDir(null).getAbsolutePath();
// http://127.0.01:8080//L05_Web/images/f10.jpg
String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);// f10.jpg
String filePath = filesPath+"/"+fileName;
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(filePath));
}
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}


return bitmap;
}

protected void onPostExecute(Bitmap bitmap) {//从联网请求图片到得到图片对象需要一定的时间, 视图可能被复用了,不需要显示
//在主线程准备显示图片之前, 需要判断是否需要显示
String newImagePath = (String) imageView.getTag();
if(newImagePath!=imagePath) {//视图已经被复用了
return;
}

//如果没有: 显示提示错误的图片(结束)
if(bitmap==null) {
imageView.setImageResource(errorImageRes);
} else {//如果有, 显示
imageView.setImageBitmap(bitmap);
}
}
}.execute();
}

/**
* 根据图片url从二级缓存中取对应的bitmap对象
* @param imagePath
* @return
*/
private Bitmap getFromSecondCache(String imagePath) {

// /storage/sdcard/Android/data/packageName/files/
String filesPath = context.getExternalFilesDir(null).getAbsolutePath();
// http://127.0.0.1:8080//L05_Web/images/f10.jpg
String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);// f10.jpg
String filePath = filesPath+"/"+fileName;

return BitmapFactory.decodeFile(filePath);
}

/**
* 根据图片url从一级缓存中取对应的bitmap对象
* @param imagePath
* @return
*/
private Bitmap getFromFirstCache(String imagePath) {
return cacheMap.get(imagePath);
}
}

 

标签:缓存,String,bitmap,imagePath,import,imageView,ListView,加载
From: https://blog.51cto.com/u_15461374/5938248

相关文章

  • 分布式锁--redis 缓存实现
    分布式锁目前几乎所有的大型网站及应用都是采用分布式部署的方式,分布式系统开发带来的优点很多,高可用,高并发,水平扩展,分开部署等。但分布式的开发也带来了一些新问题,有的时候......
  • 【Java】Spring Cache 缓存
    SpringCache一、Spring缓存抽象Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;并支......
  • mybatis一级缓存
    mybatis一级缓存缓存概念存在于内存中的临时数据为什么要使用缓存使用mybatis缓存,减少和数据库的交互次数提高执行效率缓存的使用范围经常查询并且不经常改变的数据的......
  • Pytorch中Mnist数据集的加载
    训练集train_loader=torch.utils.data.DataLoader(datasets.MNIST('data',train=True,download=True,transform=transforms.Compose([......
  • 架构与思维:再聊缓存击穿,面试是一场博弈
    1介绍在之前的一篇文章《一次缓存雪崩的灾难复盘》中,我们比较清晰的描述了缓存雪崩、穿透、击穿的各自特征和解决方案,想详细了解的可以移步。最近在配合HR筛选候选人,作......
  • yarn : 无法加载文件 C:\Users\xxx\AppData\Roaming\npm\yarn.ps1,因为在此系统
    一、前言:在Windows系统中使用WindowsPowerShell执行yarn命令,报错为:二、导致此错误的原因是:PowerShell执行策略,默认设置为Restricted不加载配置文件或运行脚本......
  • 关于.net6.0中swagger偶尔无法加载接口的问题笔记
    有时候在修改接口或者其它代码时运行发现swagger会加载不了接口列表,有时前端也无法调用接口,我遇到过两三次这样的问题了,一般swagger加载不了接口列表,如下图所示: 找不到......
  • 利用CSS、JavaScript及Ajax实现图片预加载的三大方法
    预加载图片是提高用户体验的一个很好方法。图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。这对图片画廊及图片占据很大比例的网站来说......
  • nginx反向代理部署springboot项目报404无法加载静态资源
    问题:nginx反向代理部署springboot项目报404无法加载静态资源(css,js,jpg,png...)为什么要用反向代理:springboot默认启动端口为8080,如果需要通过域名(不加端口号)直接访问sprin......
  • redis缓存穿透、缓存雪崩、缓存击穿【项目总结】
    Redis项目总结--缓存穿透、缓存雪崩、缓存击穿目录Redis项目总结--缓存穿透、缓存雪崩、缓存击穿一.缓存穿透1.什么是缓存穿透2.缓存穿透解决方案3.流程二.缓存雪崩1.什么......