zoukankan      html  css  js  c++  java
  • 使用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

  • 相关阅读:
    腾讯一面有感(移动开发岗位)
    kafka 在java中的使用
    Kafka史上最详细原理总结下
    java jdk原生的http请求工具类
    kafka(一)
    MySQL:互联网公司常用分库分表方案汇总
    密码正则
    springboot 打war包
    oracle存储过程的一些使用
    对象的深度克隆
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6933686.html
Copyright © 2011-2022 走看看