获取图像Demo(内存缓存>磁盘缓存>网络)

public class ImageLoader {
	//下载任务执行完毕后发送的message的what
	public static final int LOAD_FINISH = 101;
	public static final int NEW_TASK = 102;
	
	//线程池中线程的数量
	//(这个数量应该与设备cpu的核数相同)
	public static int Thread_Count;
	public static Context c;//上下文
	//内存缓存
	public static LruCache<String, Bitmap> MemCache;
	//(双向)任务队列
	//未来可以根据需求选择是FIFO还是LIFO
	public static LinkedBlockingDeque<Runnable> taskQueue;
	//线程池
	public static ExecutorService exec;
	//从任务队列中取下载任务的handler
	public static Handler pollHandler;
	//任务下载完毕后,用来刷新ListView条目显示下载图片的Handler
	public static Handler uiHandler;
	//"养活"pollHandler
	public static Thread pollThread;
	//磁盘缓存
	public static DiskLruCache DiskCache;
	
	//标示的作用,用来确保ImageLoader只要进行一次
	//初始化操作即可
	public static boolean isFirstTime = true;
	
	
	
	
	/**
	 * 初始化ImageLoader所有属性的值
	 * @param context
	 */
	public static void init(Context context){
		
		if(!isFirstTime){
			return;
		}
		
		//c属性赋值
		c = context;
		//获取cpu的核数为Thread_Count赋值
		Thread_Count = getNumberOfCores();
		//初始化内存缓存
		MemCache = new LruCache<String, Bitmap>((int) (Runtime.getRuntime().maxMemory()/8)){
			@Override
			protected int sizeOf(String key, Bitmap value) {
				return value.getHeight()*value.getRowBytes();
			}
			
		};
		
		//初始化磁盘缓存
		try {
			DiskCache = DiskLruCache.open(directory(), appVersion(), 1, 1024*1024*10);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		//初始化任务队列
		taskQueue = new LinkedBlockingDeque<Runnable>();
		exec = Executors.newFixedThreadPool(Thread_Count);
		//pollHandler, uiHandler
		uiHandler = new Handler(Looper.getMainLooper()){
			@Override
			public void handleMessage(Message msg) {
				//利用线程池中执行完毕的内容,来刷新ListView
				if(msg.what==LOAD_FINISH){
					//msg.obj到底放什么?
					//msg.obj放什么能解决ListView加载“动画”效果
					ValueObject vo = (ValueObject) msg.obj;
					ImageView iv = vo.iv;
					String url = vo.url;
					Bitmap bitmap = vo.bitmap;
					if(iv.getTag().toString().equals(url)){
						iv.setImageBitmap(bitmap);
					}
					
				}else{
					super.handleMessage(msg);
				}
			}
		};
		
		pollThread = new Thread(){
			@Override
			public void run() {
				Looper.prepare();
				
				pollHandler = new Handler(){
					@Override
					public void handleMessage(Message msg) {
						if(msg.what==NEW_TASK){
							//现在任务队列中被放入了新“下载任务”
							//去队列中取任务
							try {
								Runnable task = taskQueue.takeFirst();
								//将取出的任务放到线程池中执行
								exec.execute(task);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}else{
							super.handleMessage(msg);
						}
					}
					
				};
				
				
				Looper.loop();
			}
			
		};
		
		pollThread.start();
		
		isFirstTime = false;
		
	}
	private static int appVersion() {
		
		try {
			PackageInfo info = c.getPackageManager().
			getPackageInfo(c.getPackageName(), 0);
			return info.versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return 1;
	}
	private static File directory() {
		//有些环境在执行getExternalCacheDir获取
		//外部的缓存路径的时候可能会报空指针异常
		//所以这里采用了内部缓存路径
		String path = c.getCacheDir().getPath();
		return new File(path,"imageloadercache");
	}
	/**
	 * 获取url指向的图像,放到iv中显示
	 * @param url 图像路径
	 * @param iv 显示图像的ImageView
	 */
	public static void loadImage(final String url,final ImageView iv){
		if(isFirstTime){
			throw new RuntimeException("ImageLoader未做初始化");
		}
		
		//先判断,url所指向的图像是否在缓存中有保存
		
		//url转为MD5格式的字符串
		
		final String md5Url = getMD5(url);
		//设置TAG,到时候要与vo中的URL进行比对!
		iv.setTag(md5Url);
		Bitmap bitmap = MemCache.get(md5Url);
		if(bitmap!=null){
			Log.d("TAG","图像是从内存缓存中加载的");
			iv.setImageBitmap(bitmap);
			return;
		}
		
		try {
			//从磁盘缓存中试图取出url所对应的图片
			Snapshot snap = DiskCache.get(md5Url);
			if(snap!=null){
				Log.d("TAG","图像是从磁盘缓存中获取的");
				InputStream in = snap.getInputStream(0);
				bitmap = BitmapFactory.decodeStream(in);
				//将从磁盘缓存中获得的图片放到内存缓存存储一份
				MemCache.put(md5Url, bitmap);
				iv.setImageBitmap(bitmap);
				return;
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		//从网络中下载		
		taskQueue.add(new Runnable() {
			
			@Override
			public void run() {
				//下载任务
				//发起网络连接,获得图像资源
				try{
					URL u = new URL(url);
					HttpURLConnection connection = (HttpURLConnection) u.openConnection();
					connection.setRequestMethod("GET");
					connection.setDoInput(true);
					connection.connect();
					InputStream is = connection.getInputStream();
					//要对图像进行压缩
					Bitmap bitmap = compress(is,iv);
					is.close();
					//将压缩后的图像放到内存缓存中存储
					MemCache.put(md5Url, bitmap);
					//将压缩后的图像放到磁盘缓存中存储
					Editor editor = DiskCache.edit(md5Url);
					OutputStream os = editor.newOutputStream(0);
					bitmap.compress(CompressFormat.JPEG, 100, os);
					editor.commit();
					//写日志(可选操作)
					DiskCache.flush();
					
					ValueObject vo = new ValueObject(iv, md5Url, bitmap);
					Message.obtain(uiHandler, LOAD_FINISH, vo).sendToTarget();
					
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		});
		Message.obtain(pollHandler, NEW_TASK).sendToTarget();
	}
	
	/**
	 * 根据要显示的ImageView的大小对图像进行压缩
	 * @param is 图像源
	 * @param iv 未来要显示图像的ImageView
	 * @return 压缩过后的图像
	 */
	
	protected static Bitmap compress(InputStream is, ImageView iv) {
		Bitmap bitmap = null;
		try{
			
			//1)先获得原始图像(图像源)的尺寸大小
			//借助Optioins来获取图像的大小
			//is----------byte[]
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte[] buff = new byte[4096];
			int len = -1;
			while((len=is.read(buff))!=-1){
				out.write(buff, 0, len);
			}
			
			Options opts = new Options();
			opts.inJustDecodeBounds = true;
			//opts一旦设定了inJustDecodeBounds = true
			//BitmapFactory是不会返回bitmap对象,只会null
			BitmapFactory.decodeByteArray(out.toByteArray(),0, out.toByteArray().length, opts);
			int width = opts.outWidth;//图像的宽度(像素数)
			int height = opts.outHeight;//图像高度(像素数)
			//2)获取希望的宽度/高度
			int targetWidth  = iv.getWidth();//ImageView的宽度
			int targetHeight = iv.getHeight();//Imageview的高度
			//如果取ImageView宽度/高度取不到
			if(targetHeight==0||targetWidth==0){
				//可以手动指定值(80dp,100dp)
				//以当前设备屏幕的宽度/和高度来作为targetWiddth/targetHeight
				targetWidth = c.getResources().
						      getDisplayMetrics().
						      widthPixels;
				targetHeight = c.getResources().
						      getDisplayMetrics().
						      heightPixels;
			}
			
			//3)计算压缩比
			int sampleSize = 1;
			
			if(width*1.0/targetWidth>1||height*1.0/targetHeight>1){
				sampleSize = (int) Math.ceil(
						Math.max(width*1.0/targetWidth, 
								 height*1.0/targetHeight));
			}
			
			//4)压缩图像
			opts.inSampleSize = sampleSize;
			opts.inJustDecodeBounds = false;
			bitmap = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.toByteArray().length,opts);
			out.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		return bitmap;
	}
	private static String getMD5(String url) {
		String result="";
		
		try {
			MessageDigest md = MessageDigest.getInstance("md5");
			md.update(url.getBytes());
			byte[] bytes = md.digest();
			StringBuilder sb = new StringBuilder();
			for(byte b:bytes){
				String str = Integer.toHexString(b & 0xFF);
				if(str.length()==1){
					sb.append("0");
				}
				sb.append(str);
			}
			result = sb.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return result;
	}
	private static int getNumberOfCores() {
		File file = new File("/sys/devices/system/cpu/");
		File[] files = file.listFiles(new FilenameFilter() {
			
			@Override
			public boolean accept(File dir, String filename) {
				
				if(filename.matches("cpu[0-9]")){
					return true;
				}else{
					return false;
				}
			}
		});
		
		if(files.length>0){
			return files.length;
		}else{
			return 1;
		}
		
	}
	
	private static class ValueObject{
		ImageView iv;//发起下载任务的那个ImageView
		String url;//下载任务中要下载的那个地址
		Bitmap bitmap;//url所对应的图片
		public ValueObject(ImageView iv, String url, Bitmap bitmap) {
			super();
			this.iv = iv;
			this.url = url;
			this.bitmap = bitmap;
		}
	}
}


需要导入 DiskLruCache类支持。

点击打开链接


大概思想





1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看REaDME.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值