缓存原理:
- 从集合中读取:集合中没有的时候,走第二个步骤
- 访问SD卡或是从缓存目录cache中取,当这里面还没有的时候,走第三个步骤
访问网络
以下代码实现了图片缓存原理,并且可以作为一个工具类来使用:
详情请看代码:
public class ImageCache {
private LruCache<String, Bitmap> lurCache;
private File cacheDir;
private ExecutorService threadPool;
// 设置图片放置图片大小,图片路径,构造方法中实现:
public ImageCache(Context context) {
// 设置图片的大小:
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
cacheDir = context.getCacheDir();
// 存在集合中String:url
lurCache = new LruCache<String, Bitmap>(maxSize) {
// 重写sizeof的方法:计算每张图片的大小
@Override
protected int sizeOf(String key, Bitmap value) {
int rowBytes = value.getRowBytes();
int height = value.getHeight();
return rowBytes * height;
}
};
// 设置线程池中有几个线程
threadPool = Executors.newFixedThreadPool(5);
}
// 设置图片到一个imageView上:
public void display(String url, ImageView imageView) {
// 1.先从集合中取
Bitmap bitmap = getFromLruCache(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
// 从手机存放的缓存文件夹中取
bitmap = getFromCaheDir(url);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
getFromNet(url, imageView);
return;
}
private void getFromNet(String url, ImageView imageView) {
// 从网络访问获取图片,需要开辟线程,从线程池中取一个线程进行:
MyRunnable command = new MyRunnable(url, imageView);
threadPool.execute(command);
}
public class MyRunnable implements Runnable {
// 需要路径,所以需要将url传递过来
public String url;
public ImageView imageView;
MyRunnable(String url, ImageView imageView) {
this.url = url;
this.imageView = imageView;
}
@Override
public void run() {
// 开始访问网络
try {
URL urlObj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) urlObj
.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
// 访问网络成功
InputStream in = conn.getInputStream();
// 解析Inputstream 中的数据
byte[] bs = StreamUtils.readInputStream(in);
Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0,
bs.length);
if (bitmap != null) {
// 通过handle将bitmap发送出去
Message message = new Message();
message.what = 200;
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("imageView", imageView);// 为了防止图片错位的事情发生
map.put("bitmap", bitmap);
message.obj = map;
handler.sendMessage(message);
// 同时将bitmap保存到集合中
lurCache.put(url, bitmap);
// 保存到缓存文件中:
writeToCacheDir(url, bitmap);
}
return;
}
} catch (Exception e) {
e.printStackTrace();
}
// 如果走的是下面的代码:者说明网络访问是失败的:或为404,或为异常:
Message message = new Message();
message.what = 404;
handler.sendMessage(message);
}
}
// 处理消息:
public Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 200) {
HashMap<String, Object> map = (HashMap<String, Object>) msg.obj;
ImageView imageView = (ImageView) map.get("imageView");
Bitmap bitmap = (Bitmap) map.get("bitmap");
imageView.setImageBitmap(bitmap);
}
};
};
private void writeToCacheDir(String url, Bitmap bitmap) {
try {
String fileName = URLEncoder.encode(url, "UTF-8");
File imageFile = new File(cacheDir.getAbsolutePath() + "/"
+ fileName);
if (!imageFile.exists()) {
imageFile.createNewFile();
}
// 用输出流往里面写数据:
FileOutputStream fos = new FileOutputStream(imageFile);
bitmap.compress(CompressFormat.JPEG, 80, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 从缓存的文件夹中获取
private Bitmap getFromCaheDir(String url) {
// data/data/包名/cache/%%kjdjf%%kdfdl.jpg
// 在存的时候将文件名编码了下,现在也将url也编译到文件名中去
try {
String fileName = URLEncoder.encode(url, "UTF-8");
File imageFile = new File(cacheDir.getAbsolutePath() + "/"
+ fileName);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile
.getAbsolutePath());
// 保存到集合中:
lurCache.put(url, bitmap);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private Bitmap getFromLruCache(String url) {
Bitmap bitmap = lurCache.get(url);
return bitmap;
}
}