首先布局
<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);
}
}