package com.com.mr_wrong.ImageLoaderWithCaches;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.support.v7.widget.RecyclerView;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView;
import com.com.mr_wrong.ImageLoaderWithCaches.libcore.DiskLruCache;
import com.example.mr_wrong.androidstudioproject.R;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;
/**
* Created by Mr_Wrong on 2015/5/3.
* 双缓存的
*/
public class ImageLoaderWithDoubleCaches {
private Set<ASyncDownloadImage> mTasks;//储存所以下载任务的set 用于取消任务
private LruCache<String, Bitmap> mMemoryCaches;
private DiskLruCache mDiskCaches;
private ListView mListview;
public ImageLoaderWithDoubleCaches(Context context, ListView listView) {
this.mListview = listView;
mTasks = new HashSet<ASyncDownloadImage>();
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 10;
//内存缓存
mMemoryCaches = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
File cacheDir = getFileCache(context, "disk_caches");
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
try {
//磁盘缓存
mDiskCaches = DiskLruCache.open(cacheDir, 1, 1, 10 * 1024 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
}
//设置的图片都是从内存读取出来的
public void showImage(String url, ImageView imageView) {
Bitmap bitmap = getBitmapFromMemoryCaches(url);
if (bitmap == null) {
imageView.setImageResource(R.mipmap.ic_launcher);
} else {
imageView.setImageBitmap(bitmap);
}
}
public Bitmap getBitmapFromMemoryCaches(String url) {
return mMemoryCaches.get(url);
}
//加载图片到内存
public void addBitmapToMemoryCaches(String url, Bitmap bitmap) {
if (getBitmapFromMemoryCaches(url) == null) {
mMemoryCaches.put(url, bitmap);
}
}
public void loadImages(int start, int end) {
for (int i = start; i < end; i++) {
String url = Images.IMAGE_URLS[i];
Bitmap bitmap = getBitmapFromMemoryCaches(url);
if (bitmap == null) {
ASyncDownloadImage task = new ASyncDownloadImage(url);
mTasks.add(task);
task.execute(url);
} else {
ImageView imageView = (ImageView) mListview.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
/**
* 将从网络上获取的图片写到输出流
*
* @param urlString
* @param outputStream
* @return
*/
private static boolean getBitmapUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection = null;
BufferedOutputStream out = null;
BufferedInputStream in = null;
try {
final URL url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
out = new BufferedOutputStream(outputStream, 8 * 1024);
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
return true;
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
return false;
}
public void cancelAllTasks() {
if (mTasks != null) {
for (ASyncDownloadImage task : mTasks) {
task.cancel(false);
}
}
}
//给URL进行md5 防止URL中某些字符出问题
public String toMD5String(String key) {
String cacheKey;
try {
final MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(key.getBytes());
cacheKey = bytesToHexString(digest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
public void flushCache() {
if (mDiskCaches != null) {
try {
mDiskCaches.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 创建文件路径
*
* @param context
* @param cacheFileName
* @return
*/
private File getFileCache(Context context, String cacheFileName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
return new File(cachePath + File.separator + cacheFileName);
}
//任务队列 先去硬盘 没有再去网络 内存中有没有在showImage时候就判断了
class ASyncDownloadImage extends AsyncTask<String, Void, Bitmap> {
private String url;
public ASyncDownloadImage(String url) {
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
FileDescriptor fileDescriptor = null;
FileInputStream fileInputStream = null;
DiskLruCache.Snapshot snapshot = null;
String key = toMD5String(url);
try {
snapshot = mDiskCaches.get(key);
if (snapshot == null) {//硬盘中没有,从网络下载
DiskLruCache.Editor editor = mDiskCaches.edit(key);
if (editor != null) {
OutputStream outputStream = editor.newOutputStream(0);
if (getBitmapUrlToStream(url, outputStream)) {
editor.commit();//写入硬盘
} else {
editor.abort();
}
}
snapshot = mDiskCaches.get(key);//下载完成之后再去获取
}
if (snapshot != null) {//硬盘中有
fileInputStream = (FileInputStream) snapshot.getInputStream(0);
fileDescriptor = fileInputStream.getFD();
}
Bitmap bitmap = null;
if (fileDescriptor != null) {
bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
}
if (bitmap != null) {//读取硬盘中数据,加载到内存
addBitmapToMemoryCaches(params[0], bitmap);
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileDescriptor == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView = (ImageView) mListview.findViewWithTag(url);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTasks.remove(this);
}
}
}