仿Picasso框架,实现简单的图片三级缓存处理

                  最近写了一个仿Picasso框架,实现简单的图片三级缓存,主要使用了SoftReference软引用,LruCache实现内存缓存,ExecutorService线程池进行线程的控制,这样更好的处理线程数量,防止线程过多,造成内存溢出。

  大家可以直接使用:ImageManager.with(this).load("url").error(填写加载错误的图片).placeholder(填写加载中显示的图片).into(传人ImageView控件);

/**
 * picasso框架,实现简单的图片三级缓存处理
 * */
public class ImageManager {

	private static Context mContext;
	
	/**
	 * 构建出线程池,5条线程
	 * */
	private ExecutorService executorService = Executors.newFixedThreadPool(5);

	/**
	 * 内存储存图片的集合 使用lrucache缓存图片,这里不能申明在方法里,不然会被覆盖掉 4兆的大小作为缓存 SoftReference
	 * 为软引用、内存不足时,系统自动回收。
	 * */
	private LruCache<String, SoftReference<Bitmap>> imageCache = new LruCache<String, SoftReference<Bitmap>>(
			1024 * 1024 * 4);

	private Handler handler = new Handler();

	/**
	 * 获取对象的单例模式
	 * */
	private static ImageManager instance;

	private static ImageManager getInstance() {

		if (instance == null) {
			instance = new ImageManager();
		}
		return instance;
	}

	/***
	 * 初始化对象
	 * 
	 * @param context
	 * @return
	 */
	public static ImageManager with(Context context) {
		mContext = context;
		return getInstance();
	}

	/***
	 * 加载图片的url地址,返回RequestCreator对象
	 * 
	 * @param url
	 * @return
	 */
	public RequestCreatorRunnble load(String url) {
		return new RequestCreatorRunnble(url);
	}

	/**
	 * 创建者
	 * */
	public class RequestCreatorRunnble implements Runnable {

		String url;
		int holderResId;
		int errorResId;
		ImageView imageView;

		// 初始化图片的url地址
		public RequestCreatorRunnble(String url) {

			this.url = url;
		}

		/***
		 * 设置默认图片,占位图片
		 * 
		 * @param holderResId
		 * @return
		 */
		public RequestCreatorRunnble placeholder(int holderResId) {

			this.holderResId = holderResId;

			return this;

		}

		/***
		 * 发生错误加载的图片
		 * 
		 * @param errorResId
		 * @return
		 */
		public RequestCreatorRunnble error(int errorResId) {

			this.errorResId = errorResId;
			return this;
		}

		public void into(ImageView imageView) {
			// 变成全局的
			this.imageView = imageView;
			// 一进来先设置占位图片
			imageView.setImageResource(holderResId);

			// 1.去内存之中在找,有就显示,没有就往下走
			SoftReference<Bitmap> reference = imageCache.get(url);
			Bitmap cacheBitmap;
			if (reference != null) {
				cacheBitmap = reference.get();
				// 有图片就显示图片
				imageView.setImageBitmap(cacheBitmap);
				return;
			}

			// 2.去本地硬盘中找,有就显示,没有就继续往下走
			// 将文件转换成bitmap对象
			Bitmap diskBitmap = getBitmapFile();
			if (diskBitmap == null) {
				// 本地磁盘有就显示图片
				imageView.setImageBitmap(diskBitmap);
				// 保存到内存中去
				imageCache.put(url, new SoftReference<Bitmap>(diskBitmap));
				return;
			}

			// 3.连接网络请求数据
			// 前面两步都没有的话就去联网加载数据
			// 将从网络上获取的数据放到线程池去执行
			executorService.submit(this);

		}

		@Override
		public void run() {

			// 子线程
			// 处理网络请求
			URL loadUrl;
			try {
				loadUrl = new URL(url);
				HttpURLConnection conn = (HttpURLConnection) loadUrl
						.openConnection();
				// 设置请求方式
				conn.setRequestMethod("GET");
				// 设置请求时间
				conn.setConnectTimeout(2000);

				if (conn.getResponseCode() == 200) {
					InputStream is = conn.getInputStream();

					// 获取到图片进行显示
					final Bitmap bm = BitmapFactory.decodeStream(is);

					handler.post(new Runnable() {

						@Override
						public void run() {
							// 主线程
							imageView.setImageBitmap(bm);
						}
					});

					// 3.1保存到内存中
					imageCache.put(url, new SoftReference<Bitmap>(bm));
					// 3.2保存到磁盘
					// 从url中获取文件名字
					String fileName = url.substring(url.lastIndexOf("/") + 1);

					// 获取存储路径
					File file = new File(getCacheDir(),
							MD5Util.encodeMd5(fileName));
					FileOutputStream os = new FileOutputStream(file);
					// 将图片转换为文件进行存储
					bm.compress(Bitmap.CompressFormat.JPEG, 100, os);
				} else {
					// 联网失败,显示失败图片
					showError();
				}

			} catch (Exception e) {
				e.printStackTrace();
				// 显示错误的图片
				showError();
			}

		}

		/***
		 * 获取文件中的图片
		 * 
		 * @return
		 */
		private Bitmap getBitmapFile() {
			// 从url中获取文件名字
			String fileName = url.substring(url.lastIndexOf("/") + 1);
			File file = new File(getCacheDir(), MD5Util.encodeMd5(fileName));
			// 确保路径没有问题
			if (file.exists() && file.length() > 0) {
				// 返回图片
				return BitmapFactory.decodeFile(file.getAbsolutePath());

			} else {

				return null;
			}
		}

		/***
		 * 显示错误的图片
		 */
		private void showError() {
			handler.post(new Runnable() {

				@Override
				public void run() {
					imageView.setImageResource(errorResId);
				}
			});
		}

		/***
		 * 读取缓存路径目录
		 * 
		 * @return
		 */
		private File getCacheDir() {
			// 获取保存的文件夹路径
			File file;
			if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
				// 有SD卡就保存到SD卡
				file = mContext.getExternalCacheDir();
			} else {
				// 没有就保存到内部存储
				file = mContext.getCacheDir();
			}
			return file;
		}

	}

}


            


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值