**这只是一个android图片三级缓存的原理,是我从视频学到的,也是我自己整理一下,应对面试用的。真正用的话建议还是使用xutils.
建议把下面的四个类的代码看一遍,对理解三级缓存有帮助**
这里是一个自定义的图片工具类
public class MyBitmapUtils {
NetCacheUtils mNetCacheUtils;//网络图片工具
LocalCacheUtils mLocalCacheUtils;//本地图片工具类
MemoryCacheUtils memoryCacheUtils;//内存图片工具类
public MyBitmapUtils() {
memoryCacheUtils = new MemoryCacheUtils();
mLocalCacheUtils = new LocalCacheUtils();
mNetCacheUtils = new NetCacheUtils(mLocalCacheUtils, memoryCacheUtils);
}
//加载图片的方法
public void display(ImageView ivPic, String url) {
ivPic.setImageResource(R.drawable.news_pic_default);//设置加载默认图片
Bitmap bitmap=null ;
//先从从内存中读去图片
bitmap=memoryCacheUtils.getBitmapFromMemory(url);
if(bitmap!=null){
ivPic.setImageBitmap(bitmap);
return ;
}
//从本地sd卡中读去图片
bitmap=mLocalCacheUtils.getBitmapFromLocal(url);
if(bitmap!=null){
//如果读到了图片
ivPic.setImageBitmap(bitmap);
memoryCacheUtils.setBitmaptoMemory(url, bitmap);//将图片保存在内存中
return;
}
//从网络中读去图片
mNetCacheUtils.getBitmapFormNet(ivPic, url);
}
}
接下来是三个读取图片工具类
/*从网络读取图片*/
public class NetCacheUtils {
private LocalCacheUtils mlocalCacheUtils;//本地
private MemoryCacheUtils mMemoryCacheUtils;//内存
public NetCacheUtils(LocalCacheUtils localCacheUtils,
MemoryCacheUtils memoryCacheUtils) {
mlocalCacheUtils = localCacheUtils;
mMemoryCacheUtils = memoryCacheUtils;
}
// 从网络下载图片
public void getBitmapFormNet(ImageView ivPic, String url) {
new BitmapTask().execute(ivPic, url);//启动AsyncTask,参数会在doInbackground中获取 会调用下面的doInBackground(Object... params)等等方法。这可以看作是一个启动方法
}
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
private ImageView ivPic;
private String url;
// 后台耗时方法在此执行,子线程
@Override
protected Bitmap doInBackground(Object... params) {
ivPic = (ImageView) params[0];
url = (String) params[1];
ivPic.setTag(url);// 将url和imageview绑定
return downloadBitmap(url);//自己写的函数,在下面被调用
}
// 更新进度,主线程
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
// 耗时方法结束后,执行此方法,主线程
//也就是下载图片结束后
@Override
protected void onPostExecute(Bitmap result) {
if(result!=null){
String bindUrl=(String) ivPic.getTag();
if(url.equals(bindUrl)){//确保图片设置给了正确的imageview
ivPic.setImageBitmap(result);
mlocalCacheUtils.setBitmapTocal(url, result);//将图片保存到本地
mMemoryCacheUtils.setBitmaptoMemory(url, result);// 将图片保存在内存
System.out.println("从网络缓存读取图片了");
}
}
super.onPostExecute(result);
}
}
// 从网络下载图片
private Bitmap downloadBitmap(String url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
InputStream inputStram = conn.getInputStream();
// 图片压缩处理
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = 2;// 宽高都压缩为原来的二分之一,此参数需要根据图片要展示的大小来确定
option.inPreferredConfig = Bitmap.Config.RGB_565;// 设置图片格式
Bitmap bitmap = BitmapFactory.decodeStream(inputStram, null,
option);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
conn.disconnect();
}
return null;
}
}
本地缓存类
//本地缓存
class LocalCacheUtils {
public static final String CACHE_PATH=Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhbj_cache_52";//图片存到sd卡中的地址
// 从本地sdcard读图片
public Bitmap getBitmapFromLocal(String url) {
try{
//存的时候把图片的的地址用MD5加密后作为存储的名字,所以取得时候也要把地址加密。
String filename=MD5Encoder.encode(url);
File file=new File(CACHE_PATH,filename);
if(file.exists()){
Bitmap bitmap=BitmapFactory.decodeStream(new FileInputStream(file));
return bitmap;
}
}
catch(Exception e){
e.printStackTrace();
}
return null;
}
// 向sdcard写图片
public void setBitmapTocal(String url,Bitmap bitmap) {
String filename;
try {
filename = MD5Encoder.encode(url);
File file=new File(CACHE_PATH, filename);
File parentFile=file.getParentFile();
if(!parentFile.exists()){
//如果文件夹不存在,创建文件夹
parentFile.mkdir();
//将图片保存在本地
bitmap.compress(CompressFormat.JPEG, 100,
new FileOutputStream(file));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
内存缓存
public class MemoryCacheUtils {
// private HashMap<String , SoftReference<Bitmap>> mMemoryCache=new
// HashMap<String, SoftReference<Bitmap>>();
/*异步加载图片的例子,网上也比较多,大部分用了HashMap<String, SoftReference<Drawable>> imageCache ,但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃,所以我这里用得是LruCache来缓存图片,当存储Image的大小大于LruCache设定的值,系统自动释放内存,这个类是3.1版本中提供的,如果你是在更早的Android版本中开发,则需要导入android-support-v4的jar包(这里要注意咯)*/
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 获取最大内存模拟器默认是16M
mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
return byteCount;
}
};
}
// 从内存中读数据
public Bitmap getBitmapFromMemory(String url) {
// 防止内存溢出,但下面的方法实际中不用
// SoftReference<Bitmap> softReference=mMemoryCache.get(url);
// if(softReference!=null){
// Bitmap bitmap=softReference.get();
// return bitmap;
//
//
// }
return mMemoryCache.get(url);
}
// 写内存
public void setBitmaptoMemory(String url, Bitmap bitmap) {
// SoftReference<Bitmap> softReference = new
// SoftReference<Bitmap>(bitmap);
// mMemoryCache.put(url, softReference);
mMemoryCache.put(url, bitmap);
}
}
调用举例
private MyBitmapUtils myutils;
myutils.display(holder.ivPic,item.listimage );
//注释 自己的bitmaoutils
//注释 holder.ivPic 一个holder中的imgivew.
//注释 item.listimage 一个图片的地址
只需知道两个参数一个是imageivew,一个是url就行
首先会从内存中找图片,内存中没有,会在从本地sd卡中读取,如果从本地找到图片,会显示到imgview中,然后顺便存到内存中,如果没有在从网络中读取,从网络中读到流后,生成bitmap 顺便存到内存与sd卡中。
我只是一个菜鸟,视频里就是这么讲的,怎么实际中要用的话,建议用xutils,因为三级缓存它帮你实现了。