Android学习之 有关图片缓存问提的代码封装<二>

            背景:在上一篇中,主要介绍了内存缓存封装类和SD卡上临时文件缓存封装类,这一篇中,我们来封装一下 从网络获取图片的工具类及异步加载图片类

            1、从网络获取图片的工具类:ImageHttpUtil.java

package com.ice.android.common.util.imagecache;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

/**
 * 从网络获取图片工具类
 * @author ice
 */
public class ImageHttpUtil {

	private static final String TAG = "ImageHttpUtil";
	
	/**
	 * 请求网络  根据图片url从网络上获取图片
	 * 这里使用 apache的 HttpClient请求网络
	 * @param mImageParams
	 * @return
	 */
	public static Bitmap getImageData(String url){
		HttpGet getRequest = new HttpGet(url);
		try {
			HttpResponse response = new DefaultHttpClient().execute(getRequest);
			int statusCode = response.getStatusLine().getStatusCode();
			if(statusCode != HttpStatus.SC_OK){
				Log.w(TAG, "Error: "+statusCode+" while retrieving bitmap from "+url);
				return null;
			}
			HttpEntity entity = response.getEntity();
			if(entity != null){
				InputStream inputStream = null;
				try {
					inputStream = entity.getContent();
					/* return BitmapFactory.decodeStream(inputStream);  // Bug on slow connections, fixed in future release.  */
					
					FlushedInputStream fis = new FlushedInputStream(inputStream);
					return BitmapFactory.decodeStream(fis);
				} catch (IllegalStateException e) {
					e.printStackTrace();
				}finally{
					if(inputStream != null){
						inputStream.close();
					}
					entity.consumeContent();
				}
			}
		} catch (ClientProtocolException e) {
			getRequest.abort();  // 中断请求
			Log.w(TAG, "Error: "+e.getMessage()+" while retrieving bitmap from "+url);
			e.printStackTrace();
		} catch (IOException e) {
			getRequest.abort();  // 中断请求
			Log.w(TAG, "I/O Error: "+e.getMessage()+" while retrieving bitmap from "+url);
			e.printStackTrace();
		}
		
		return null;
	}
	
	
	/**
	 * 继承 FilterInputStream <过滤的输入流>
	 * 能过滤掉/跳过输入流中的某些字节
	 * @author ice
	 *
	 */
	private static class FlushedInputStream extends FilterInputStream {
		public FlushedInputStream(InputStream inputStream) {
			super(inputStream);
		}

		/**
		 * 重写 skip() 方法
		 * 跳过和丢弃此输入流中数据的 n个字节,完成输入流的字节过滤
		 */
		@Override
		public long skip(long n) throws IOException {
			long totalBytesSkipped = 0L;
			while (totalBytesSkipped < n) {
				long bytesSkipped = in.skip(n - totalBytesSkipped);
				if (bytesSkipped == 0L) {
					int b = read();
					if (b < 0) {
						break; // we reached EOF
					} else {
						bytesSkipped = 1; // we read one byte
					}
				}
				totalBytesSkipped += bytesSkipped;
			}
			return totalBytesSkipped;
		}
	}
	
	
}


        2,异步加载网络图片/缓存图片类:AsynImageLoader.java

package com.ice.android.common.util.imagecache;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.util.Log;


/**
 * 异步加载图片缓存 类
 * 单例模式
 * @author ice
 *
 */
public class AsynImageLoader {

	private static final String TAG = "AsynImageLoader";
	
	/** 线程池数量  */
	private static final int THREAD_NUM = 3; 
	/** 线程池  */
	private ExecutorService executorService;
	
	/** 内存缓存对象  */
	private ImageMemCache memCache;
	/** sd卡 文件缓存对象  */
	private ImageFileCache fileCache;
	
	private static AsynImageLoader instance;
	
	
	/**
	 * 单例模式
	 * @param memCache
	 * @param fileCache
	 */
	private AsynImageLoader() {
		executorService = Executors.newFixedThreadPool(THREAD_NUM);
		this.memCache = new ImageMemCache();
		this.fileCache = new ImageFileCache();
	}


	/**
	 * 获取实例
	 * @return
	 */
	public static synchronized AsynImageLoader getInstance(){
		if(instance == null){
			instance = new AsynImageLoader();
		}
		return instance;
	}
	
	
	/**
	 * 加载图片数据
	 * @param mImageParams
	 * @param mHandler
	 */
	public void loadImageData(ImageParams mImageParams,Handler mHandler){
		executorService.submit(new ImgLoadTask(mImageParams,mHandler));
	}
	
	
	/**
	 * 从网络上获取图片数据,并将图片缓存到内存或是sdcard上
	 * @param imageParams
	 * @return
	 */
	private Bitmap loadNetImage(ImageParams imageParams){
		Bitmap imageData = ImageHttpUtil.getImageData(imageParams.getUrl().trim());
		if(imageData != null){
			memCache.addBitmapToCache(imageParams, imageData);
			
			fileCache.addBitmapToSdcard(imageParams, imageData);
		}else{
			Log.d(TAG, "获取网络图片数据失败,url = "+imageParams.getUrl());
		}
		
		return imageData;
	}
	
	
	/**
	 * 从本地缓存中获取图片数据
	 * 获得一个图片的数据,从三个地方获取,首先是内存缓存,然后是文件(sdcard)缓存,最后从网络获取
	 * @param imageParams
	 * @return
	 */
	public Bitmap loadCacheImage(ImageParams imageParams){
		Bitmap imageData = null;
		// 从内存缓存中获取图片
		imageData = memCache.getImageData(imageParams);
		if(imageData == null){
			// 从文件(sdcard)缓存中获取图片
			imageData = fileCache.getImageData(imageParams);
		}
		return imageData;
	}

	
	
	/**
	 * 图片加载子线程任务  内部类
	 * @author ice
	 * 
	 * java.util.concurrent.Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。
	 * 但是 Runnable 不会返回结果
	 *
	 */
	private class ImgLoadTask implements Callable<Void>{

		private ImageParams imageParams;
		private Handler handler;
		
		public ImgLoadTask(ImageParams mImageParams, Handler mHandler) {
			this.imageParams = mImageParams;
			this.handler = mHandler;
		}

		@Override
		public Void call() throws Exception {
			Message msg = new Message();
			msg.obj = loadNetImage(imageParams);
			if(msg.obj != null){
				// 将加载得到的图片对象 通过Message承载发送给Handler处理
				handler.sendMessage(msg);
			}
			return null;
		}
	}
	
	
	
	
}


ok ! 到这里关于App应用开发中 有关图片缓存问题的代码已封装完毕!

小吕, 初转Android开发  算是Android新人,愿与大家共同学习!


你可能感兴趣的:(android,线程池,图片,缓存,图片缓存)