- 一
-
-
-
-
- 1. 简介
-
- 现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多。
-
- 现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响。当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略。总之,图片缓存是很重要而且是必须的。
-
-
-
- 2.图片缓存的原理
-
- 实现图片缓存也不难,需要有相应的cache策略。这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中。当根据url向网络拉取图片的时候,先从内存中找,如果内存中没有,再从缓存文件中查找,如果缓存文件中也没有,再从网络上通过http请求拉取图片。在键值对(key-value)中,这个图片缓存的key是图片url的hash值,value就是bitmap。所以,按照这个逻辑,只要一个url被下载过,其图片就被缓存起来了。
-
-
-
-
- 关于Java中对象的软引用(SoftReference),如果一个对象具有软引用,内存空间足够,垃 圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高 速缓存。使用软引用能防止内存泄露,增强程序的健壮性。
-
-
-
-
- 从代码上来说,采用一个ImageManager来负责图片的管理和缓存,函数接口为public void loadBitmap(String url, Handler handler) ;其中url为要下载的图片地址,handler为图片下载成功后的回调,在handler中处理message,而message中包含了图片的信息以及bitmap对象。ImageManager中使用的ImageMemoryCache(内存缓存)、ImageFileCache(文件缓存)以及LruCache(最近最久未使用缓存)会在后续文章中介绍。
-
-
-
-
- 3.代码ImageManager.java
-
-
-
-
- public class ImageManager implements IManager
- {
- private final static String TAG = "ImageManager";
-
- private ImageMemoryCache imageMemoryCache;
-
- private ImageFileCache imageFileCache;
-
-
- public static HashMap<String, Handler> ongoingTaskMap = new HashMap<String, Handler>();
-
-
- public static HashMap<String, Handler> waitingTaskMap = new HashMap<String, Handler>();
-
-
- final static int MAX_DOWNLOAD_IMAGE_THREAD = 4;
-
- private final Handler downloadStatusHandler = new Handler(){
- public void handleMessage(Message msg)
- {
- startDownloadNext();
- }
- };
-
- public ImageManager()
- {
- imageMemoryCache = new ImageMemoryCache();
- imageFileCache = new ImageFileCache();
- }
-
-
- public void loadBitmap(String url, Handler handler)
- {
-
- Bitmap bitmap = getBitmapFromNative(url);
-
- if (bitmap != null)
- {
- Logger.d(TAG, "loadBitmap:loaded from native");
- Message msg = Message.obtain();
- Bundle bundle = new Bundle();
- bundle.putString("url", url);
- msg.obj = bitmap;
- msg.setData(bundle);
- handler.sendMessage(msg);
- }
- else
- {
- Logger.d(TAG, "loadBitmap:will load by network");
- downloadBmpOnNewThread(url, handler);
- }
- }
-
-
- private void downloadBmpOnNewThread(final String url, final Handler handler)
- {
- Logger.d(TAG, "ongoingTaskMap'size=" + ongoingTaskMap.size());
-
- if (ongoingTaskMap.size() >= MAX_DOWNLOAD_IMAGE_THREAD)
- {
- synchronized (waitingTaskMap)
- {
- waitingTaskMap.put(url, handler);
- }
- }
- else
- {
- synchronized (ongoingTaskMap)
- {
- ongoingTaskMap.put(url, handler);
- }
-
- new Thread()
- {
- public void run()
- {
- Bitmap bmp = getBitmapFromHttp(url);
-
-
-
- synchronized (ongoingTaskMap)
- {
- ongoingTaskMap.remove(url);
- }
-
- if(downloadStatusHandler != null)
- {
- downloadStatusHandler.sendEmptyMessage(0);
-
- }
-
- Message msg = Message.obtain();
- msg.obj = bmp;
- Bundle bundle = new Bundle();
- bundle.putString("url", url);
- msg.setData(bundle);
-
- if(handler != null)
- {
- handler.sendMessage(msg);
- }
-
- }
- }.start();
- }
- }
-
-
-
- public Bitmap getBitmap(String url)
- {
-
- Bitmap bitmap = imageMemoryCache.getBitmapFromMemory(url);
- if (bitmap == null)
- {
-
- bitmap = imageFileCache.getImageFromFile(url);
- if (bitmap != null)
- {
-
- imageMemoryCache.addBitmapToMemory(url, bitmap);
- }
- else
- {
-
- bitmap = getBitmapFromHttp(url);
- }
- }
- return bitmap;
- }
-
-
- public Bitmap getBitmapFromNative(String url)
- {
- Bitmap bitmap = null;
- bitmap = imageMemoryCache.getBitmapFromMemory(url);
-
- if(bitmap == null)
- {
- bitmap = imageFileCache.getImageFromFile(url);
- if(bitmap != null)
- {
-
- imageMemoryCache.addBitmapToMemory(url, bitmap);
- }
- }
- return bitmap;
- }
-
-
- public Bitmap getBitmapFromHttp(String url)
- {
- Bitmap bmp = null;
-
- try
- {
- byte[] tmpPicByte = getImageBytes(url);
-
- if (tmpPicByte != null)
- {
- bmp = BitmapFactory.decodeByteArray(tmpPicByte, 0,
- tmpPicByte.length);
- }
- tmpPicByte = null;
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
-
- if(bmp != null)
- {
-
- imageFileCache.saveBitmapToFile(bmp, url);
-
- imageMemoryCache.addBitmapToMemory(url, bmp);
- }
-
- return bmp;
- }
-
-
- public byte[] getImageBytes(String url)
- {
- byte[] pic = null;
- if (url != null && !"".equals(url))
- {
- Requester request = RequesterFactory.getRequester(
- Requester.REQUEST_REMOTE, RequesterFactory.IMPL_HC);
-
- MyResponse myResponse = null;
- MyRequest mMyRequest;
- mMyRequest = new MyRequest();
- mMyRequest.setUrl(url);
- mMyRequest.addHeader(HttpHeader.REQ.ACCEPT_ENCODING, "identity");
- InputStream is = null;
- ByteArrayOutputStream baos = null;
- try {
- myResponse = request.execute(mMyRequest);
- is = myResponse.getInputStream().getImpl();
- baos = new ByteArrayOutputStream();
- byte[] b = new byte[512];
- int len = 0;
- while ((len = is.read(b)) != -1)
- {
- baos.write(b, 0, len);
- baos.flush();
- }
- pic = baos.toByteArray();
- Logger.d(TAG, "icon bytes.length=" + pic.length);
-
- }
- catch (Exception e3)
- {
- e3.printStackTrace();
- try
- {
- Logger.e(TAG,
- "download shortcut icon faild and responsecode="
- + myResponse.getStatusCode());
- }
- catch (Exception e4)
- {
- e4.printStackTrace();
- }
- }
- finally
- {
- try
- {
- if (is != null)
- {
- is.close();
- is = null;
- }
- }
- catch (Exception e2)
- {
- e2.printStackTrace();
- }
- try
- {
- if (baos != null)
- {
- baos.close();
- baos = null;
- }
- }
- catch (Exception e2)
- {
- e2.printStackTrace();
- }
- try
- {
- request.close();
- }
- catch (Exception e1)
- {
- e1.printStackTrace();
- }
- }
- }
- return pic;
- }
-
-
- private void startDownloadNext()
- {
- synchronized(waitingTaskMap)
- {
- Logger.d(TAG, "begin start next");
- Iterator iter = waitingTaskMap.entrySet().iterator();
-
- while (iter.hasNext())
- {
-
- Map.Entry entry = (Map.Entry) iter.next();
- Logger.d(TAG, "WaitingTaskMap isn't null,url=" + (String)entry.getKey());
-
- if(entry != null)
- {
- waitingTaskMap.remove(entry.getKey());
- downloadBmpOnNewThread((String)entry.getKey(), (Handler)entry.getValue());
- }
- break;
- }
- }
- }
-
- public String startDownloadNext_ForUnitTest()
- {
- String urlString = null;
- synchronized(waitingTaskMap)
- {
- Logger.d(TAG, "begin start next");
- Iterator iter = waitingTaskMap.entrySet().iterator();
-
- while (iter.hasNext())
- {
- Map.Entry entry = (Map.Entry) iter.next();
- urlString = (String)entry.getKey();
- waitingTaskMap.remove(entry.getKey());
- break;
- }
- }
- return urlString;
- }
-
-
- public static Bitmap toRoundCorner(Bitmap bitmap, int pixels)
- {
- if(bitmap == null)
- return null;
-
- Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
-
- final int color = 0xff424242;
- final Paint paint = new Paint();
- final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
- final RectF rectF = new RectF(rect);
- final float roundPx = pixels;
-
- paint.setAntiAlias(true);
- canvas.drawARGB(0, 0, 0, 0);
- paint.setColor(color);
- canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
-
- paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- canvas.drawBitmap(bitmap, rect, rect, paint);
-
- return output;
- }
-
- public byte managerId()
- {
- return IMAGE_ID;
- }
- }
-
posted @
2016-03-16 22:54
Sharley
阅读(
156)
评论()
编辑
收藏
举报