当前位置:网站首页>android中的图片三级缓存
android中的图片三级缓存
2022-07-27 14:48:00 【白马镇的少年】
三级缓存,顾名思义是有三个层级的操作:
1、内存缓存
2、本地缓存
3、网络
首先咱们来说说内存
内存包括:强引用、软引用、弱引用、虚引用。
强引用是默认的引用方式, 即使内存溢出,也不会回收。
软引用(softReference), 内存不够时, 会考虑回收。
弱引用 (WeakReference)内存不够时, 更会考虑回收。
虚引用(PhantomReference) 内存不够时, 最优先考虑回收!
一般我们常用到的引用就是强引用,比如引用创建一个成员变量里面的引用。对于GC来说, SoftReference的强度明显低于 SrongReference。SoftReference修饰的引用,其告诉GC:我是一个 软引用,当内存不足的时候,我指向的这个内存是可以给你释放掉的。一般对于这种占用内存资源比较大的,又不是必要的变量;或者一些占用大量内存资源的一些缓存的变量,就需要考虑 SoftReference。对于GC来说, WeakReference 的强度又明显低于 SoftReference 。 WeakReference 修饰的引用,其告诉GC:我是一个弱引用,对于你的要求我没有话说,我指向的这个内存是可以给你释放掉的。虚引用其实和上面讲到的各种引用不是一回事的,他主要是为跟踪一个对象何时被GC回收。在android里面也是有用到的:FileCleaner.java 。这些避免内存溢出的引用方式在Android 2.3+的版本上已经不再起太大作用, 因为垃圾回收器会频繁回收非强引用的对象, Android官方建议使用LRUCache。所以当我们用软引用进行内存缓存时会发现内存中的资源会被系统频繁回收。最终是从本地进行读数据。
LRUCache(Least Recently Used),就是近期最少使用的算法,核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象。LruCache中维护了一个集合LinkedHashMap,该LinkedHashMap是以访问顺序排序的。当调用put()方法时,就会在结合中添加元素,并调用trimToSize()判断缓存是否已满,如果满了就用LinkedHashMap的迭代器删除队尾元素,即近期最少访问的元素。当调用get()方法访问缓存对象时,就会调用LinkedHashMap的get()方法获得对应集合元素,同时会更新该元素到队头。
创建一个管理类BitmapUtils
import android.graphics.Bitmap;
import android.util.Log;
import android.widget.ImageView;
import com.wisdtour.interact.R;
public class BitmapUtils {
private NetCacheUtils mNetCacheUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
public BitmapUtils(){
mMemoryCacheUtils=new MemoryCacheUtils();
mLocalCacheUtils=new LocalCacheUtils();
mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);
}
/**
* 用来三级缓存显示图片
* @param ivPic
* @param url
*/
public void disPlay(ImageView ivPic, String url) {
ivPic.setImageResource(R.drawable.s);
Bitmap bitmap;
// 1. 内存缓存 速度很快不浪费流量 优先
bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);
if (bitmap!=null){
ivPic.setImageBitmap(bitmap);
Log.e("TAG", "从内存获取图片啦");
return;
}
//本地缓存 速度快 不浪费流量 其次
bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
if(bitmap !=null){
ivPic.setImageBitmap(bitmap);
Log.e("TAG", "从本地获取图片啦");
//从本地获取图片后,保存至内存中
mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
return;
}
//网络缓存 速度慢浪费流量 最后
mNetCacheUtils.getBitmapFromNet(ivPic,url);
}
}
依次创建三个类
MemoryCacheUtils
import android.graphics.Bitmap;
import android.util.LruCache;
public class MemoryCacheUtils {
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手机最大允许内存的1/8,即超过指定内存,则开始回收
//需要传入允许的内存最大值,虚拟机默认内存16M,真机不一定相同
mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){
//用于计算每个条目的大小
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getByteCount();
return byteCount;
}
};
}
/**
* 从内存中读图片
* @param url
*/
public Bitmap getBitmapFromMemory(String url) {
//Bitmap bitmap = mMemoryCache.get(url);//1.强引用方法
/*2.弱引用方法
SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url);
if (bitmapSoftReference != null) {
Bitmap bitmap = bitmapSoftReference.get();
return bitmap;
}
*/
if(url==null||"".equals(url)){
return null;
}
Bitmap bitmap = mMemoryCache.get(url);
return bitmap;
}
/**
* 往内存中写图片
* @param url
* @param bitmap
*/
public void setBitmapToMemory(String url, Bitmap bitmap) {
//mMemoryCache.put(url, bitmap);//1.强引用方法
/*2.弱引用方法
mMemoryCache.put(url, new SoftReference<>(bitmap));
*/
mMemoryCache.put(url,bitmap);
}
}
本地缓存 LocalCacheUtils
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class LocalCacheUtils {
private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/images";
/**
* 从本地读取图片
* @param url
*/
public Bitmap getBitmapFromLocal(String url){
String fileName = null;//把图片的url当做文件名,并进行MD5加密
try {
fileName = MD5Encoder.encode(url); //这里加不加密无所谓
File file=new File(CACHE_PATH,fileName);
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 从网络获取图片后,保存至本地缓存
* @param url
* @param bitmap
*/
public void setBitmapToLocal(String url, Bitmap bitmap){
try {
String fileName = MD5Encoder.encode(url);//把图片的url当做文件名,并进行MD5加密
File file=new File(CACHE_PATH,fileName);
//通过得到文件的父文件,判断父文件是否存在
File parentFile = file.getParentFile();
if (!parentFile.exists()){
parentFile.mkdirs();
}
//把图片保存至本地
bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
} catch (Exception e) {
e.printStackTrace();
}
}
}
网络缓存NetCacheUtils
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.widget.ImageView;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class NetCacheUtils {
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;
public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
mLocalCacheUtils = localCacheUtils;
mMemoryCacheUtils = memoryCacheUtils;
}
public NetCacheUtils() {
}
/**
* 从网络下载图片
*
* @param ivPic 显示图片的imageview
* @param url 下载图片的网络地址
*/
public void getBitmapFromNet(ImageView ivPic, String url) {
new BitmapTask().execute(ivPic, url);//启动AsyncTask
}
public void getBitmapFromNet(View ivPic, String url) {
new BitmapTask_view().execute(ivPic, url);//启动AsyncTask
}
public Bitmap getBitmapFromNet(final String url) {
//启动AsyncTask
return null;
}
/**
* AsyncTask就是对handler和线程池的封装
* 第一个泛型:参数类型
* 第二个泛型:更新进度的泛型
* 第三个泛型:onPostExecute的返回结果
*/
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
private ImageView ivPic;
private String url;
/**
* 后台耗时操作,存在于子线程中
*
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(Object[] params) {
ivPic = (ImageView) params[0];
url = (String) params[1];
return downLoadBitmap(url);
}
/**
* 更新进度,在主线程中
*
* @param values
*/
@Override
protected void onProgressUpdate(Void[] values) {
super.onProgressUpdate(values);
}
/**
* 耗时方法结束后执行该方法,主线程中
*
* @param result
*/
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
ivPic.setImageBitmap(result);
System.out.println("从网络缓存图片啦.....");
//从网络获取图片后,保存至本地缓存
mLocalCacheUtils.setBitmapToLocal(url, result);
//保存至内存中
mMemoryCacheUtils.setBitmapToMemory(url, result);
}
}
}
/**
* AsyncTask就是对handler和线程池的封装
* 第一个泛型:参数类型
* 第二个泛型:更新进度的泛型
* 第三个泛型:onPostExecute的返回结果
*/
@SuppressLint("NewApi")
class BitmapTask_view extends AsyncTask<Object, Void, Bitmap> {
private View ivPic;
private String url;
/**
* 后台耗时操作,存在于子线程中
*
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(Object[] params) {
ivPic = (View) params[0];
url = (String) params[1];
return downLoadBitmap(url);
}
/**
* 更新进度,在主线程中
*
* @param values
*/
@Override
protected void onProgressUpdate(Void[] values) {
super.onProgressUpdate(values);
}
/**
* 耗时方法结束后执行该方法,主线程中
*
* @param result
*/
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
//ivPic.setImageBitmap(result);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//Android系统大于等于API16,使用setBackground
ivPic.setBackground(new BitmapDrawable(result));
} else {
//Android系统小于API16,使用setBackground
ivPic.setBackgroundDrawable(new BitmapDrawable(result));
}
System.out.println("从网络缓存图片啦.....");
//从网络获取图片后,保存至本地缓存
mLocalCacheUtils.setBitmapToLocal(url, result);
//保存至内存中
mMemoryCacheUtils.setBitmapToMemory(url, result);
}
}
}
/**
* 网络下载图片
*
* @param url
* @return
*/
public Bitmap downLoadBitmap(String url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
//图片压缩
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;//宽高压缩为原来的1/2
options.inPreferredConfig = Bitmap.Config.ARGB_4444;
//Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);
Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
} finally {
if (conn != null) {
conn.disconnect();
}
}
return null;
}
}
MD5
import java.security.MessageDigest;
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();
}
}
使用
BitmapUtils bitmapUtils = new BitmapUtils(); //bitmapUtils.disPlay(test,"http://ww4.sinaimg.cn/large/006uZZy8jw1faic21363tj30ci08ct96.jpg"); bitmapUtils.disPlay(test,url);
边栏推荐
- DRF use: get request to get data (small example)
- CCF-201312-1
- ADAMS中转动整个模型
- C language output string in reverse order
- ARIMA model selection and residuals
- 2021 national vocational college skills competition (secondary vocational group) network security competition questions (9) ideas
- TP5 query empty two cases
- 4-digit random data
- Log management
- The method of inserting degree in word
猜你喜欢

Mazak handwheel maintenance Mazak little giant CNC machine tool handle operator maintenance av-eahs-382-1

Collection! 0 basic open source data visualization platform flyfish large screen development guide

CCF-201312-1

The difference and use between get request and post request

201403-1

清晰的认识Torchvision(思维导图版)

Excel提取重复项

The new JMeter function assistant is not under the options menu - in the toolbar

Insert pictures in word to maintain high DPI method

Your password does not satisfy the current policy requirements (modify MySQL password policy setting simple password)
随机推荐
Opencv (IV) -- image features and target detection
Kmeans implementation
Excel提取重复项
Cubemx combined with IAR engineering transplantation
Your password does not satisfy the current policy requirements (modify MySQL password policy setting simple password)
Leetcode234 question - simple method to judge palindrome linked list
training on multiple GPUs pytorch
Brief description of tenant and multi tenant concepts in cloud management platform
DEX and AMMS of DFI security
The solution to the memory exhaustion problem when PHP circulates a large amount of data
Mysql5.7 master-slave hot standby settings on CentOS
重新配置cubemx后,生成的代码用IAR打开不成功
Script file ‘D:\programs\anaconda3\Scripts\pip-script. py‘ is not present.
论文缩小
Characters generated by JMeter function assistant in jmeter5.3 and later versions cannot be copied when they are grayed out
my_ls小结
The 21st - -- the 30th time
Log management
知网、万方数据库免费下载论文------比连接学校内网速度快数倍不止(有的学校万方数据库不支持下载)
4-digit random data