图片的三级缓存原理

来源:互联网 发布:手机淘宝商品历史价格 编辑:程序博客网 时间:2024/05/19 20:00

首先布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="us.mifeng.imgloderyuanli.MainActivity" 
    android:orientation="vertical">


    <Button 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="bt"
        android:text="点击下载"
        />
    <ImageView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/iv"
        />


</LinearLayout>

然后就自己在创建一个类 名为 Utils

Utils类

package us.mifeng.imgloderyuanli.utils;


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
/*
 * 文件操作工具类: 储存和读取图片  存储和读取文件
 */
public class Utils {
private Context mContext;
public Utils(Context context){
this.mContext=context;
}
//判断SD卡是否存在,存在返回true  不存在返回flase
//Environment.getExternalStorageState():获取sd卡的状态  Environment.MEDIA_MOUNTED:当前SD存在
public boolean ISSDcard(){
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
return true;
}
return false;
}
/*
* 获取文件目录的方法

*/
private String getFile() {
String str = null;
str = mContext.getExternalCacheDir().getAbsolutePath();
return str;
}
/*
* 存储图片的方法
*/
public void savaBitmap(String name,Bitmap bit){
//判断sdk是否在,不存在直接return
if (!ISSDcard()) 
return;
//获取图片完整存储路径,以图片网址为图片名称存储  路径为 /mnt/sdcard/android/data/catch/name  虚拟机不同 保存的路径也不相同
String filename = getFile()+"/"+name;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//图片压缩
bit.compress(CompressFormat.PNG, 100, bos);
File file = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(file);
//写文件
fos.write(bos.toByteArray());
fos.flush();
fos.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 读取图片的方法
*/
public Bitmap readBitmap(String name){
Bitmap bitmap = null;
if (!ISSDcard()) 
return bitmap;
//获取图片存储的完整路径
String filename = getFile()+"/"+name;
bitmap= BitmapFactory.decodeFile(filename);
return bitmap;
}
}

Loader类

package us.mifeng.imgloderyuanli.thread;


import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
import us.mifeng.imgloderyuanli.utils.Utils;
/**
 * 图片的三级缓存
 *
 */
public class Loader1 {
private Utils utils;//工具类
private Context context;
private final static int MAX_POLLS = 5;//申明一个最大的开启线程池
private ExecutorService thread_pool;//声明一个线程池
private Set<ImageView> imgs = new HashSet<ImageView>();//创建一个储存图片的set集合
private int max_size = (int) (Runtime.getRuntime().maxMemory())/1024/5;//规定每个线池的最大内容
//Lurcache:类似于强引用缓存的,一但超出最大值,会自动将前面的扔出内存,便于垃圾回收机制回收
//Lurcache:储存方式和map相似,用的k和v存值得方式,便于图片查找
private LruCache<String ,Bitmap> lru = new LruCache<String ,  Bitmap>(max_size){
@SuppressLint("NewApi")
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount()/1024;
};
};
private Handler hand = new Handler(){
public void handleMessage(android.os.Message msg) {
if (msg.what==1) {
Bitmap bitmap = (Bitmap) msg.obj;
String name = msg.getData().getString("imgname");
//遍历set集合,进行对比
Iterator<ImageView> it = imgs.iterator();
while (it.hasNext()) {
ImageView img = it.next();
String tag = (String) img.getTag();
//将子线程出来的图片名称和控件保存的相对应的图片名称进行比较,如果相同就设置
if (tag.equals(name)) {
img.setImageBitmap(bitmap);
return;
}
}

}
};
};
public void Load(String name, ImageView img,Context ctx){
//为空就跳出
if (name==null) 
return;
if (img==null)  
return;
this.context=ctx;
Bitmap bitmap;
//name 进行过滤
String name1 = name.replace("/", "").replace("_", "").replace(".","").replace(":", "");
//将img添加到set集合
img.setTag(name1);
//从lru中查找图片
imgs.add(img);
bitmap = lru.get(name1);//k,v->从lru中获取图片
if (bitmap!=null) {
img.setImageBitmap(bitmap);
return;
}
//从本地获取图片
if (utils==null) {
utils = new Utils(ctx);
bitmap=utils.readBitmap(name1);
if (bitmap!=null) {
img.setImageBitmap(bitmap);
//将图片添加到lru中
lru.put(name1, bitmap);
return;

}
}
//从网络中下载
if (thread_pool==null) {
thread_pool=Executors.newFixedThreadPool(MAX_POLLS);
}
//准备下载图片
thread_pool.execute(new ImgThread(name));
}
//图片异步加载内部类
private class ImgThread implements Runnable{
private String name;

public ImgThread(String name) {
this.name=name;
}
@Override
public void run() {
//开始网络下载
try {
URL url = new URL(name);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream());
String name1 = name.replace(".", "").replace("_", "").replace("/", "").replace(":", "");
//将下载下来的图片再次添加到SD卡中和Lru中
if (bitmap!=null) {
utils.savaBitmap(name1, bitmap);
lru.put(name1, bitmap);
Message mess = hand.obtainMessage();
mess.what=1;
mess.obj=bitmap;
Bundle bundle = new Bundle();
bundle.putString("imgname", name1);
mess.setData(bundle);
hand.sendMessage(mess);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

最后就是Maintivity类了

package us.mifeng.imgloderyuanli;


import us.mifeng.imgloderyuanli.thread.Loader1;
import us.mifeng.imgloderyuanli.utils.Utils;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;


public class MainActivity extends Activity {


private ImageView mIv;
private Loader1 loader1;
private String name = "http://c.hiphotos.baidu.com/image/pic/item/d31b0ef41bd5ad6e6fe8710c85cb39dbb7fd3cc6.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIv = (ImageView) findViewById(R.id.iv);
loader1 = new Loader1();
}
public void bt(View v){
loader1.Load(name, mIv, this);
}
}

                                             
0 0
原创粉丝点击