您的位置:首页 > 理论基础 > 计算机网络

(MyStudy:一)三级缓存:首先是内存-文件(外存)-网络三级缓存机制。

2016-07-13 14:51 405 查看
三级缓存:首先是内存-文件(外存)-网络三级缓存机制。



首先:

框架需要一个接入方法NGImageloadHelper.Java:

/**
* 图片加载框架使用帮助类
* Created by nangua on 2016/7/8.
*/
public class NGImageloadHelper {
/**
* 处理图片
* @param view
* @param url
*/
public static void displayImage(ImageView view,
String url) {
NGDownloadImage.getInstance().addTask(url,
view);
NGDownloadImage.getInstance().doTask();
}
}


然后,使用具体的缓存实现类NGDownloadImage:

首先判断传入的url对应图片是否在内外存中,如果不在,则添加进线程池的自定义任务队列中,这里传入的任务是自定义的实现Callble接口的任务TaskWithResult,在带回调参数的执行方法call中执行一个自定义的handler—-TaskHandler,该TaskHandler的handlerMessage方法内部根据传入的图片类型判断,执行相应的下载方法(通过HttpUrlConnection实现)并移除taskmap中对应的图片任务。

/**
* 图片加载类
* Created by nangua on 2016/7/8.
*/
public class NGDownloadImage {
private ExecutorService executorService; //线程池服务
private NGImageMemoryCache imageMemoryCache;
private NGImageFileCache imageFileCache;
private NGDownloadImageMode downloadImageMode; //图片实例
private Map<String, View> taskMap;
private static NGDownloadImage instance; //自身私有化实例
private int POOL_SIZE = 5;//线程池自定义大小

private NGDownloadImage() {
final int cpuNums = Runtime.getRuntime().availableProcessors();//cpu数
executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);
imageMemoryCache = new NGImageMemoryCache();
imageFileCache = new NGImageFileCache();
downloadImageMode = new NGDownloadImageMode();
taskMap = new HashMap<>();
}

//获得唯一实例
public static synchronized NGDownloadImage getInstance() {
if (instance == null) {
instance = new NGDownloadImage();
}
return instance;
}

/**
* 添加任务
*
* @param url
* @param img
*/
public void addTask(String url, ImageView img) {
addTask(null, url, img, null);
}

public void addTask(Object parent, String url, View img,
NGImageCallback callback) {
if (img == null) {
return;
}

if (TextUtils.isEmpty(url)) {
return;
}

if (callback != null) {
downloadImageMode = new NGDownloadImageMode();
downloadImageMode.setCallback(callback);
downloadImageMode.setParent(parent);
downloadImageMode.setImgUrl(url);
img.setTag(downloadImageMode);
} else {
img.setTag(url);
}

//生成Bitmap
final Bitmap bitmap = imageMemoryCache.getBitmapFromCache(url);
//如果缓存里有
if (bitmap != null) {
//如果有实现的回调接口,则用回调接口加载图片
if (callback != null) {
callback.imageLoaded(parent, img, bitmap, downloadImageMode);
} else {
//如果没有,则直接设置该图片为bitmap
if (img instanceof ImageView)
((ImageView) img).setImageBitmap(bitmap);
}
} else {
//如果缓存没有这个图片
if (taskMap != null) {
//添加到任务集合里去
synchronized (taskMap) {
final String mapKey = Integer.toString(img.hashCode());
if (!taskMap.containsKey(mapKey)) {
taskMap.put(mapKey, img);
}
}
}
}
}

public void doTask() {
if (taskMap == null) {
return;
} else {
synchronized (taskMap) {
Collection<View> collection = taskMap.values();
for (View view : collection) {
if (view != null) {
Object object = view.getTag();
String url = "";
if (object instanceof NGDownloadImageMode) {
url = ((NGDownloadImageMode) object).getImgUrl();
} else {
url = (String) object;
}
if (!TextUtils.isEmpty(url)) {
loadImage(url, view);
}
}
}
}
}
}

private void loadImage(final String url, final View img) {
loadImage(url, img, null);
}

private void loadImage(final String url, final View img,
NGImageCallback callback) {
executorService.submit(new TaskWithResult(new TaskHandler(url, img,
callback), url));
}

private class TaskWithResult implements Callable<String> {
private String url;
private Handler handler;

public TaskWithResult(Handler handler, String url) {
this.url = url;
this.handler = handler;
}

@Override
public String call() throws Exception {
// TODO Auto-generated method stub
final Message message = handler.obtainMessage(0, getBitmap(url));
handler.sendMessage(message);
return url;
}
}

private class TaskHandler extends Handler {
private String url;
private View img;
private NGImageCallback callback;

public TaskHandler(String url, View img, NGImageCallback callback) {
this.url = url;
this.img = img;
this.callback = callback;
}

@Override
public void handleMessage(Message msg) {
final Object object = img.getTag();

if (object instanceof NGDownloadImageMode) {
final NGDownloadImageMode imageMode = (NGDownloadImageMode) object;
imageMode.getCallback().imageLoaded(imageMode.getParent(), img,
(Bitmap) msg.obj, imageMode);

if (taskMap != null) {
taskMap.remove(Integer.toString(img.hashCode()));
}
} else if (object instanceof String) {
if (callback != null) {
callback.imageLoaded(null, img, (Bitmap) msg.obj, url);
} else {
if (object.equals(url) && msg.obj != null) {
final Bitmap bitmap = (Bitmap) msg.obj;
if (bitmap != null) {
if (img instanceof ImageView) {
((ImageView) img).setImageBitmap(bitmap);
}
}
}
}
if (taskMap != null) {
taskMap.remove(Integer.toString(img.hashCode()));
}
}
}
}

/**
* @param url
* @return Bitmap
*/
public Bitmap getBitmap(String url) {
Bitmap bitmap = imageMemoryCache.getBitmapFromCache(url);
if (bitmap == null) {
bitmap = imageFileCache.getImage(url);
if (bitmap == null) {
bitmap = getBitmapFromUrl(url);
if (bitmap != null) {
imageMemoryCache.addBitmapToCache(url, bitmap);
imageFileCache.saveBmpToSd(url,bitmap);
}
} else {
imageMemoryCache.addBitmapToCache(url, bitmap);
}
}
return bitmap;
}

public static Bitmap getBitmapFromUrl(String path) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if (conn.getResponseCode() == 200) {
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

public interface NGImageCallback {
public void imageLoaded(Object parent, View img, Bitmap imageBitmap,
NGDownloadImageMode callBackTag);

public void imageLoaded(Object parent, View img, Bitmap imageBitmap,
String imageUrl);
}
}


内存缓存实现:

通过强&软引用配合使用实现内存缓存机制,强引用使用HashMap实现,软引用使用线程安全的 ConcurrentHashMap实现(实现原理是锁分离技术,使用多个锁来控制对hash表的不同部分的修改,内部使用段(Segment)来表示这些不同的部分,每个段是一个小的hashtable,可并发运行),淘汰算法如下:

/**
* 初始化
* 淘汰最老的键
*/
protected NGImageMemoryCache() {
//使用LinkedHashMap保证有序读取
hashMap = new LinkedHashMap<String, Bitmap>(MAX_CACHE_CAPACITY, 0.75f, true) {
//移除hashmap中最老的键值
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
if (size() > MAX_CACHE_CAPACITY) {
mSoftBitmapCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
return true; //返回true则移除最老的键值
} else {
return false;
}
}
};
}


外存缓存实现:

很简单这里就只讲一下思路了,把图片文件存储到本地指定文件夹中,注意进行剩余容量判断及时清除最老的图片就行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  缓存机制 内存 网络