使用LruCache和DiskLruCache來下載圖片,
LruCache是一個很好用的圖片緩衝工具:
主要做法是:滑動圖片時將圖片的bitmap緩衝在LruCache<String, Bitmap>中,退出程式後將圖片緩衝進檔案裡,採用DiskLruCache mDiskLruCache
所以我們必須設定一個圖片緩衝的地址:
public void setImageCache(){ String strPath = null; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File sdFile = Environment.getExternalStorageDirectory(); strPath = sdFile.getAbsolutePath() + "/pic/"; File cacheFile = new File(strPath); if(!cacheFile.exists()){ cacheFile.mkdir(); } } else{ String strCacheDir = this.getCacheDir().getAbsolutePath(); strPath = strCacheDir + "/pic/"; } setCachePath(strPath); }private void setCachePath(String strPicCachePath){if(TextUtils.isEmpty(strPicCachePath)){return;}m_strPicCachePath = strPicCachePath;File cacheFile = new File(strPicCachePath); if(!cacheFile.exists()){ cacheFile.mkdir(); }}public String getCacheBmpPath(String strUrl){if(TextUtils.isEmpty(m_strPicCachePath) || TextUtils.isEmpty(strUrl)){return "";}return m_strPicCachePath + StringUtil.MD5Encode(strUrl) + mFileExName;//".bmp";}
然後寫List的adapter:
private class ListAdapter extends BaseAdapter implements OnScrollListener {protected List<ShopData> items = new ArrayList<ShopData>();protected static final int FETCH_IMAGE_MSG = 1;private LruCache<String, Bitmap> mMemoryCache;protected HashSet<ImageView> mItemsMissingImages = new HashSet<ImageView>();protected ImageLoaderHandler mHandler;protected ImageLoader mImageFetcher;public static final int TIMEOUT = 30000;//逾時時間30秒private DiskLruCache mDiskLruCache; public ListAdapter() {super();mHandler = new ImageLoaderHandler();int maxMemory = (int) Runtime.getRuntime().maxMemory();int mCacheSize = maxMemory / 8;// 給LruCache分配1/8 4MmMemoryCache = new LruCache<String, Bitmap>(mCacheSize) {// 必須重寫此方法,來測量Bitmap的大小@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}}; try {mDiskLruCache = DiskLruCache .open(new File(m_strPicCachePath), getAppVersion(MainActivityTest.this), 1, 10 * 1024 * 1024);} catch (IOException e) {e.printStackTrace();} }/** * 將緩衝記錄同步到journal檔案中。 */public void fluchCache() {if (mDiskLruCache != null) {try {mDiskLruCache.flush();} catch (IOException e) {e.printStackTrace();}}}@Overridepublic int getCount() {return items.size();}@Overridepublic Object getItem(int position) {return items.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ShopDataTag tag = new ShopDataTag();if (convertView == null) {convertView = mInflater.inflate(R.layout.listitem, null);tag.name = (TextView) convertView.findViewById(R.id.name);tag.shopInfo = (TextView) convertView.findViewById(R.id.info);tag.icon = (ImageView) convertView.findViewById(R.id.image_icon);convertView.setTag(tag);} else {tag = (ShopDataTag) convertView.getTag();}TextView name = tag.name;TextView info = tag.shopInfo;ImageView imageView = tag.icon;ShopData data = items.get(position);name.setText(data.name);info.setText(data.info);imageView.setTag(data.url);setContactPhoto(data.url, imageView);return convertView;}protected void setContactPhoto(String url,ImageView viewToUse) {if(TextUtils.isEmpty(url)) {viewToUse.setImageResource(R.drawable.avatar);}else{//先看mMemoryCache裡能不能得到bitmapBitmap bitmap = mMemoryCache.get(url); if (bitmap != null) {viewToUse.setImageBitmap(bitmap);} else {Snapshot snapShot = null;FileDescriptor fileDescriptor = null;FileInputStream fileInputStream = null;try {//因為mDiskLruCache會把key作為檔案名稱,所以把url通過md5轉換為keyfinal String key = hashKeyForDisk(url);snapShot = mDiskLruCache.get(key);//如果snapShot為空白,就是沒找到對應的檔案if (snapShot == null) {//這裡去下載fetchImage(viewToUse);}else{fileInputStream = (FileInputStream) snapShot.getInputStream(0);fileDescriptor = fileInputStream.getFD();if (fileDescriptor != null) {bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);}//如果解析檔案成bitmap失敗,重新下載if(!TextUtils.isEmpty(url) && bitmap != null){mMemoryCache.put(url, bitmap);viewToUse.setImageBitmap(bitmap);}else{fetchImage(viewToUse);}}}catch(IOException ex) {ex.printStackTrace();}finally{if (fileDescriptor == null && fileInputStream != null) {try {fileInputStream.close();} catch (IOException e) {}}}}}}private void fetchImage(ImageView viewToUse) {viewToUse.setImageResource(R.drawable.avatar);mItemsMissingImages.add(viewToUse);if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) {sendFetchImageMessage(viewToUse);}}public String <strong>hashKeyForDisk</strong>(String key) { 將key轉換為md5檔案return StringUtil.MD5Encode(key);}// image downloaderprivate class ImageLoaderHandler extends Handler {@Overridepublic void handleMessage(Message message) {if (isFinishing()) {return;}switch (message.what) {case FETCH_IMAGE_MSG: {final ImageView imageView = (ImageView) message.obj;if (imageView == null) {break;}final String url = (String) imageView.getTag();if (TextUtils.isEmpty(url)) {break;}Bitmap map = getBitmapFromMemCache(url);if (map == null) {break;}synchronized (imageView) {final String myUrl = (String) imageView.getTag();if (TextUtils.equals(url, myUrl)) {imageView.setImageBitmap(map);mItemsMissingImages.remove(imageView);} else {}}break;}}}public void clearImageFecthing() {removeMessages(FETCH_IMAGE_MSG);}}private class ImageLoader implements Runnable {String url;private ImageView mImageView;public ImageLoader(String url, ImageView imageView) {this.url = url;this.mImageView = imageView;}public void run() {if (isFinishing()) {return;}if (Thread.interrupted()) {return;}FileDescriptor fileDescriptor = null;FileInputStream fileInputStream = null;Snapshot snapShot = null;try {final String key = hashKeyForDisk(url);snapShot = mDiskLruCache.get(key);if (snapShot == null) {// 如果沒有找到對應的緩衝,則準備從網路上請求資料,並寫入緩衝DiskLruCache.Editor editor = mDiskLruCache.edit(key);if (editor != null) {OutputStream outputStream = editor.newOutputStream(0);boolean flag = downloadImage(url, outputStream);if (flag) {editor.commit();} else {editor.abort();}}// 緩衝被寫入後,再次尋找key對應的緩衝snapShot = mDiskLruCache.get(key);}//這裡應該刪除對應的檔案if (snapShot != null) {fileInputStream = (FileInputStream) snapShot.getInputStream(0);fileDescriptor = fileInputStream.getFD();}// 將快取資料解析成Bitmap對象Bitmap bitmap = null;if (fileDescriptor != null) {bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);}if (bitmap != null) {// 將Bitmap對象添加到記憶體緩衝當中mMemoryCache.put(url, bitmap);}} catch (IOException e) {e.printStackTrace();} finally {if (fileDescriptor == null && fileInputStream != null) {try {fileInputStream.close();} catch (IOException e) {}}}if (Thread.interrupted()) {return;}Message msg = new Message();msg.what = FETCH_IMAGE_MSG;msg.obj = mImageView;mHandler.sendMessage(msg);}}public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); } public boolean downloadImage(String strUrl,OutputStream fos) {URL getUrl = null;Bitmap bitmap = null;BufferedOutputStream out = null;BufferedInputStream in = null;try {getUrl = new URL(strUrl);} catch (MalformedURLException ex) {Log.e("HttpUtil", "get MalformedURL", ex);return false;}InputStream input = null;HttpURLConnection conn = null;try {conn = (HttpURLConnection)getUrl.openConnection();conn.setConnectTimeout(TIMEOUT);conn.setReadTimeout(TIMEOUT);conn.setDoInput(true);conn.connect();input = conn.getInputStream();in = new BufferedInputStream(input, 8 * 1024);out = new BufferedOutputStream(fos, 8 * 1024);int b;while ((b = in.read()) != -1) {out.write(b);}return true;} catch (Exception ex) {Log.e("HttpUtil", "downloadImage", ex);} catch(OutOfMemoryError ex){ex.printStackTrace();} finally {try {if(out != null){out.close();out = null;}if (in != null){in.close();in = null;}if (conn != null){conn.disconnect();conn = null;}} catch (Exception ex) {Log.e("HttpUtil", "downloadImage finally", ex);}}return false;}private boolean getResponse(InputStream input, OutputStream os, byte[] data) throws IOException{if(input == null || os == null || data == null){return false;}int i = 0;while( (i = input.read(data)) != -1){os.write(data, 0, i);os.flush();}os.flush();return true;}private void processMissingImageItems(AbsListView view) {for (ImageView iv : mItemsMissingImages) {sendFetchImageMessage(iv);}}protected void sendFetchImageMessage(ImageView view) {final String url = (String) view.getTag();if (TextUtils.isEmpty(url)) {return;}mImageFetcher = new ImageLoader(url, view);synchronized (MainActivityTest.this) {if (sImageFetchThreadPool == null) {sImageFetchThreadPool = Executors.newFixedThreadPool(3);}sImageFetchThreadPool.execute(mImageFetcher);}}public void clearImageFetching() {synchronized (MainActivityTest.this) {if (sImageFetchThreadPool != null) {sImageFetchThreadPool.shutdownNow();sImageFetchThreadPool = null;}}mHandler.clearImageFecthing();}public void clearMessages() {if (mHandler != null) {try {mHandler.removeCallbacksAndMessages(null);} catch (java.lang.Throwable th) {}mHandler = null;}}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {mScrollState = scrollState;if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {clearImageFetching();} else {processMissingImageItems(view);}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}}private class ShopDataTag {TextView name;TextView shopInfo;ImageView icon;}
:
代碼:http://download.csdn.net/detail/baidu_nod/7777137