Android图片 * 缓存开发
作者:WhatYouSeeMe 发布时间:2023-12-03 22:42:43
标签:Android,图片缓存
因为目前工程无法使用第三方,只能搞一个 * 缓存了 * 缓存分为内存缓存,本地缓存,网络缓存;缓存的步骤依次是网络,内存,本地,然后取的顺序为内存,本地,网络。在加载图片时引用时尽量采用弱引用避免出现图片过多产生OOM.。
1、内存缓存,android为我们提供LruCache=其中维护着一个LinkedHashMap。LruCache可以用来存储各种类型的数据,我们设置它的大小,一般是系统最大存储空间的1/8.
public class MemoryCacheUtil {
private LruCache<String, Bitmap> lruCache;
public MemoryCacheUtil(){
int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);
// 一般获取当前应用的最大内存的1/8作为LruCache的容量
lruCache = new LruCache<String, Bitmap>(maxSize){
// 设置当前添加的图片的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight();
}
};
}
// 从内存缓存取图片
public Bitmap getBitmap(String url){
return lruCache.get(url);
}
// 在内存缓存存图片
public void putBitmap(String url,Bitmap bitmap){
lruCache.put(url, bitmap);
}
}
2、本地缓存根据url,获取本地文件,把url进行md5加密,作为文件名,保证文件的正确性.
MD5加密工具类
public class MD5Encoder {
public static String encode(String string) throws Exception {
byte[] hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10) {
hex.append("0");
}
hex.append(Integer.toHexString(b & 0xFF));
}
return hex.toString();
}
}
本地缓存
public class LocalCacheUtil {
private String CACHE_URl;
private MemoryCacheUtil memoryCacheUtil;
public LocalCacheUtil(MemoryCacheUtil memoryCacheUtil){
// 初始化本地存储的路径
CACHE_URl = Environment.getExternalStorageDirectory().getAbsoluteFile()+ "/test";
this.memoryCacheUtil = memoryCacheUtil;
}
// 从本地sdcard取图片
public Bitmap getBitmap(String url){
// 根据url,获取本地文件,把url进行md5加密,作为文件名
try {
String fileName = MD5Encoder.encode(url);
File file = new File(CACHE_URl, fileName);
if(file.exists()){// 判断当前文件是否存在
// 把当前文件转换成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
// 需往内存中存一份
memoryCacheUtil.putBitmap(url, bitmap);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 往本地存图片的方法
public void saveBitmap(String url,Bitmap bitmap){
try {
String fileName = MD5Encoder.encode(url);
File file = new File(CACHE_URl, fileName);
// 判断是否需要创建父目录
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
// 把Bitmap对象保存到文件中 质量越高压缩速度越慢
OutputStream stream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, stream);//第一个参数可以设置图片格式,第二个图片压缩质量,第三个为图片输出流
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、网络缓存使用异步加载AsyncTask,使用其有二种原因:
1.doInBackground运行在子线程,做网络请求耗时操作,避免主线程堵塞;
2.onPreExecute和onPostExecute便于更新UI提高用户体验。
public class NetCacheUtil {
private MemoryCacheUtil memoryCacheUtil;
private LocalCacheUtil localCacheUtil;
private ListView lv_image_list;
public NetCacheUtil(MemoryCacheUtil memoryCacheUtil,LocalCacheUtil localCacheUtil){
this.memoryCacheUtil = memoryCacheUtil;
this.localCacheUtil = localCacheUtil;
}
public void display(ImageView imageView ,String url, ListView lv_image_list){
this.lv_image_list = lv_image_list;
new MyAsyncTask(imageView).execute(new Object[]{url,imageView});
}
class MyAsyncTask extends AsyncTask<Object, Void, Bitmap>{
private ImageView imageView;
private int position;
public MyAsyncTask(ImageView imageView2) {
position = (Integer) imageView2.getTag();
}
// 运行在主线程,做准备操作,在doInBackground之前,可以放置加载条提高用户体验
@Override
protected void onPreExecute() {
super.onPreExecute();
}
// 运行在子线程,做耗时操作
@Override
protected Bitmap doInBackground(Object... params) {
// 获取url,下载图片
String url = (String) params[0];
// 获取ImageView
imageView = (ImageView) params[1];
try {
// 下载图片
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.connect();// 连接网络
// 获取响应码
int resCode = conn.getResponseCode();
if(resCode==200){// 访问成功
// 把服务器返回的输入流转换成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
// 保存到本地和内存
memoryCacheUtil.putBitmap(url, bitmap);
localCacheUtil.saveBitmap(url, bitmap);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 运行在主线程,更新界面,在doInBackground之后
@Override
protected void onPostExecute(Bitmap result) {
// 判断线程开始时,那个位置是否还在Listview中
ImageView view = (ImageView) lv_image_list.findViewWithTag(position);
if(view!=null){
view.setImageBitmap(result);
}
super.onPostExecute(result);
}
}
}
4、封装 * 缓存形成ImageUtil,因内存缓存中取速度较快,所以先从内存缓存中取,取不到->本地缓存中取,取不到->网络缓存中取。
public class ImageUtils {
private MemoryCacheUtil memoryCacheUtil;
private LocalCacheUtil localCacheUtil;
private NetCacheUtil netCacheUtil;
public ImageUtils(){
memoryCacheUtil = new MemoryCacheUtil();
localCacheUtil = new LocalCacheUtil(memoryCacheUtil);
netCacheUtil = new NetCacheUtil(memoryCacheUtil,localCacheUtil);
}
public void display(ImageView imageView, String url, ListView lv_photo_list) {
Bitmap bitmap = null;
/**
* 因内存缓存中取速度较快
* 内存缓存中取,取不到->本地缓存中取,取不到->网络缓存中取
*/
bitmap = memoryCacheUtil.getBitmap(url);//从内存缓存取图片
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
bitmap = localCacheUtil.getBitmap(url);//从本地缓存取图片
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
return;
}
// 开启线程访问网络,下载图片,并且展示
netCacheUtil.display(imageView, url,lv_photo_list);
}
}
来源:http://blog.csdn.net/wangjiangjun0815/article/details/77717820


猜你喜欢
- static 表示静态,它可以修饰属性,方法和代码块。1.static修饰属性(类变量),那么这个属性就可以用类名.属性名来访问,也就是使这
- 数据库事务是后端开发中不可缺少的一块知识点。Spring为了更好的支撑我们进行数据库操作,在框架中支持了两种事务管理的方式: 编程式事务声明
- 问题描述设有n个会议的集合C={1,2,…,n},其中每个会议都要求使用同一个资源(如会议室),而在同一时间内只能有一
- 快速排序实现: namespace QuickSort { class QuickSort { public static void Sor
- 前言Spring Boot常用注解整理提示:以下是本篇文章正文内容,下面案例可供参考一、@SpringBootApplication此注解是
- using System;using System.Collections.Generic;using System.ComponentMo
- 目录1.基于注释声明缓存1.1@EnableCaching1.2@Cacheable1.2.1默认key生成规则1.2.2声明自定义key
- 实现流程初始化一定数量的任务处理线程和缓存线程池,用户每次调用接口,开启一个线程处理。假设初始化5个处理器,代码执行 BlockingQue
- 概述在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何
- 1.scope 作用域Spring 管理的 bean 是根据 scope 来⽣成的,表示 bean 的作⽤域,共4种,默认值是 single
- Android 列表组件 ListView列表组件是开发中经常用到组件,使用该组件在使用时需要为它提供适配器,由适配器提供来确定显示样式和显
- 密封类和密封接口是 Kotlin 中允许创建受限类层次结构的两个特性。这两个构造用于定义一组有限的可能子类型,并防止在声明的层次结构之外定义
- 概述从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章.算法的衡量标准当我们需要衡量一个算法的的优越性, 通常会
- 1、idea构建web项目idea构建web项目的超级详细教程,一步一步来,完全没问题!1、新建一个空项目2、新建java模块,名为webD
- 接触了这么久的View,总不能一直停留在View里,现在开始呢,就要学习一个新的知识点:SurfaceView,实际上SurfaceView
- 一、下载安装包 1. JDK1.8百度云下载路径:百度网盘下载链接: https://pan.baidu
- 在Android中偶尔会用到开关,Switch就是一个简单易使用的不错的控件。首先,在布局中添加上Switch控件:<Switch &
- 使用javafx更新UIJavaFx如果在子线程中更新UI,不论是task还是runable都会报错java.lang.IllegalSta
- XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。对于XML本身的语法知识
- 以前,使用github(git)结合 IntelliJ IDEA ,可以把自己本地的测试代码,使用github网站,添加到版本管理。这样就可