使用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 4M
			mMemoryCache = new LruCache<String, Bitmap>(mCacheSize) {

				// 必须重写此方法,来測量Bitmap的大小
				@Override
				protected 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(); } } } @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public 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里能不能得到bitmap Bitmap 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转换为key final 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 downloader private class ImageLoaderHandler extends Handler { @Override public 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; } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mScrollState = scrollState; if (scrollState == OnScrollListener.SCROLL_STATE_FLING) { clearImageFetching(); } else { processMissingImageItems(view); } } @Override public 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

原文地址:https://www.cnblogs.com/jzssuanfa/p/6933686.html