一个方便的图片加载框架——ImageViewEx
我的博客:http://mrfufufu.github.io/
一、前言
最近在整理项目中的一些代码,以备即将开展的新项目中使用,刚刚整理到一个图片加载的 lib,用起来非常的简单,和 picasso 或者谷歌的 Volley 等都一样,只需要一行代码就能完成图片加载的逻辑。
项目地址:ImageViewEx
项目效果:
二、使用
先给出使用方法:首先在布局文件中加入如下代码:
<mrfu.imageviewex.lib.ImageViewExandroid:id="@+id/imageview"android:layout_width="match_parent"android:layout_height="200dp"android:layout_below="@+id/toolbar"android:scaleType="centerCrop" />
如果是要使用圆形或者圆角的图片,只需要将 ImageViewEx
改成 RoundImageView
就可以了。
在 Java 代码中,这样写就可以了
ImageViewEx imageviewex = (ImageViewEx)findViewById(R.id.imageview);
RoundImageView roundimageview1 = (RoundImageView)findViewById(R.id.roundimageview1);
RoundImageView roundimageview2 = (RoundImageView)findViewById(R.id.roundimageview2);
imageviewex.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");
roundimageview1.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");
roundimageview2.setConer(10, 10);//设置圆角图片
roundimageview2.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");
三、 原理
先给出类关系图
使用方式非常简单,现在大概来分析一下这个框架的原理:
框架的加载方式主要还是通过 http 请求的 get 方式拿到图片,然后将其保存在 SD 卡中,将 SD 卡中的图片转化为 Bitmap 对象,通过 LruMemoryCache
缓存方式存到内存中。并将其加载到对应 View 上去。
主要类就是 ImageViewEx
和 ImageLoader
了
1、 ImageViewEx.java
这个类的主要功能就是设置加载时的默认图片,调用ImageLoader 类的loadImageAsync进行加载图片,对加载完成后的回调进行处理。都在loadImage(url)中体现了:
public void loadImage(String url) {mUrl = url;setImageBitmap(null);//设置加载时的默认图片if (defaultDrawable != null) {setImageDrawable(defaultDrawable);} else if (defaultImg != null) {setImageBitmap(defaultImg);} else {setImageDrawable(defaultImage);}//调用ImageLoader,进行图片加载ImageLoader.ImageRequest request = new ImageLoader.ImageRequest(url, this);ImageLoader.get().loadImageAsync(request, mHttpCallback);
}protected void toMeasure(Bitmap bitmap){};AbsHttpCallback mHttpCallback = new AbsHttpCallback() {@Overridepublic void onSuccess(final ImageRequest request, final Bitmap bitmap) {if(!request.url.equals(mUrl)) {return ;}toMeasure(bitmap);final ImageView iv = (ImageView)request.cookie;if(request.inMemory) {iv.setImageBitmap(bitmap);return ;}//设置动画handler.post(new Runnable() {@Overridepublic void run() {if(request.url.equals(mUrl)) {setImageWithAnimation(iv, bitmap);}}});}
2、 ImageLoader.java
使用最大运行内存的十六分之一作为 LruMemoryCache 的缓存大小,如果超过了这个大小,系统会自动将其释放掉。
在加载的过程中,线程池可以开启的最多任务数为 MAX_BLOCK_QUEUE_SIZE
个,balanceTasks()这个方法,保证了队列的最大任务数:
/*** balance tasks*/
private void balanceTasks() {BlockingQueue<Runnable> queue = mExecutorPool.getQueue();if (queue == null) { return ;}int poolSize = queue.size();if (poolSize > MAX_BLOCK_QUEUE_SIZE) { //保留队尾MAX_BLOCK_QUEUE_SIZE个队列其他清理掉int keep = poolSize - MAX_BLOCK_QUEUE_SIZE;List<Runnable> list = new ArrayList<Runnable>();int i = 0;while (queue.size() > 0) {i++;Runnable r = queue.remove();if (i >= keep) {list.add(r);} else {LocalTask task = (LocalTask) r;mTaskQueue.remove(task.httpRequest.url);}}queue.clear();queue.addAll(list);}
}
在内部类 LocalTask 中进行加载的逻辑,主要看 run() 方法,先根据 url 拿到 SD 卡中的存储路径pathName,将 pathName 解析成 Bitmap 对象,如果不为 null 表示 SD 卡中有该图片,直接取 SD 卡中的图片,否则删除这个文件,并通过 HttpRequestGet 去下载该图片,下载完成后会回调 requestFinished 方法,并调用 notifySuccess 方法,注意,不管成功还是失败,都需要将其从任务队列 mTaskQueue 中删除。
/*** local task**/
private class LocalTask implements Runnable, HttpGetProgressCallback {private ImageRequest httpRequest;private AbsHttpCallback callback;public LocalTask(ImageRequest request, AbsHttpCallback callback) {this.httpRequest = request;this.callback = callback;}@Overridepublic void run() {String pathName = FileStore.cachePathForKey(httpRequest.url);if (!TextUtils.isEmpty(pathName)) {Bitmap bitmap = decodeBitmap(pathName);if(bitmap != null) {notifySuccess(httpRequest, callback, bitmap);return ;} else {new File(pathName).delete();}}callback.onStart(httpRequest);HttpRequestGet httpGet = new HttpRequestGet(httpRequest.url, this);httpGet.run();}@Overridepublic void requestFinished(String url, String pathName) {Bitmap bitmap = decodeBitmap(pathName);if(bitmap != null) {notifySuccess(httpRequest, callback, bitmap);} }@Overridepublic void requestFailed(String url, String errorStr) {notifyFailure(httpRequest, callback, HttpErrorResult.HTTP_GET_FAIL);}@Overridepublic void progressPublish(String url, int progress) {callback.onProgress(httpRequest, progress);}}
/*** notify success tasks* @param httpRequest* @param callback*/
private void notifySuccess(ImageRequest httpRequest, AbsHttpCallback callback, Bitmap bitmap) {mBitmapCache.put(httpRequest.url, bitmap);Set<ItemTask> set = mTaskQueue.get(httpRequest.url);if(set != null){for(ItemTask task : set){task.callback.onSuccess(task.httpRequest, bitmap);}set.clear();mTaskQueue.remove(httpRequest.url);}
}
private void notifyFailure(ImageRequest httpRequest, AbsHttpCallback callback, HttpErrorResult error) {Set<ItemTask> set = mTaskQueue.get(httpRequest.url);if(set != null){for(ItemTask task : set){task.callback.onFailure(task.httpRequest, HttpErrorResult.HTTP_GET_FAIL);}set.clear();mTaskQueue.remove(httpRequest.url);}
}
3、 HttpRequestGet.java
get 请求成功后,创建文件路径,将请求到的数据存储到文件中,通知回调成功或者失败的结果。
4、 RoundImageView.java
这个类就比较简单了,继承自 ImageViewEx,功能是 设置圆形图片,主要就是重写了 onDraw(canvas); 方法,在这个方法里调用了 Canvas 的 drawRoundRect 方法。注意,如果要设置成圆角图片 则需要调用 setConer(x,y); 如果不调用表示圆形图片:
@Override
protected void onDraw(Canvas canvas) { Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bitmap);Paint paint = new Paint(1);paint.setColor(Color.BLACK);if (x != 0 && y != 0) {c.drawRoundRect(new RectF(0.0F, 0.0F, getWidth(), getHeight()),x, y, paint);}else {c.drawRoundRect(new RectF(0.0F, 0.0F, getWidth(), getHeight()),getWidth()/2, getHeight()/2, paint);}Paint paint0 = new Paint();new PorterDuffXfermode(PorterDuff.Mode.DST_IN);paint0.setFilterBitmap(false);paint0.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));try{Drawable drawable = getDrawable();if (drawable != null) {int saveCount = canvas.saveLayer(0.0F, 0.0F, getWidth(),getHeight(), null, 31);drawable.setBounds(0, 0, getWidth(), getHeight());drawable.draw(canvas);canvas.drawBitmap(bitmap, 0.0F, 0.0F, paint0);canvas.restoreToCount(saveCount);}}catch(Exception e){e.printStackTrace();}catch(Throwable t){t.printStackTrace();}
}
基本的就是这样,框架其实很简单,将其抽取出来作为一个框架来用的话,还是很方便的。对了如果要显示下载进度,只需要调用 HttpGetProgressCallback 接口就可以了,这个可以自己去封装,我就不搞了,哈哈,后期如果有这个需求可以考虑加上。嗯。。。后面再更新吧。
一个方便的图片加载框架——ImageViewEx相关推荐
- Android设计一个图片加载框架
本文不是具体编码去实现一个图片加载的框架,而是从理论上来讲解设计一个图片加载框架的注意事项和涉及的知识点,提供一个思路,或者帮助童鞋们应付面试.目前Android 发展至今优秀的图片加载框架太多,例如 ...
- Android图片加载框架
这篇文章主要和大家一起动手编写Android图片加载框架,从内部原理到具体实现来详细介绍如何开发一个简洁而实用的Android图片加载缓存框架,感兴趣的小伙伴们可以参考一下 开发一个简洁而实用的And ...
- 图片加载框架Glide的简单使用
图片加载框架Glide的相关使用 一.搭建环境 1.引入依赖,设置网络权限 implementation 'com.github.bumptech.glide:glide:3.7.0' 代码实现 1. ...
- 图片加载框架Picasso - 源码分析
简书:图片加载框架Picasso - 源码分析 前一篇文章讲了Picasso的详细用法,Picasso 是一个强大的图片加载缓存框架,一个非常优秀的开源库,学习一个优秀的开源库,,我们不仅仅是学习它的 ...
- Android Glide图片加载框架(三)缓存机制
文章目录 一.缓存简介 二.缓存用法 内存缓存方式 磁盘缓存方式 三.缓存KEY 四.内存缓存 内存缓存流程 五.磁盘缓存 磁盘缓存流程 Android Glide图片加载框架系列文章 Android ...
- Android Glide图片加载框架(二)源码解析之into()
文章目录 一.前言 二.源码解析 1.into(ImageView) 2.GlideContext.buildImageViewTarget() 3.RequestBuilder.into(Targe ...
- Android Glide图片加载框架(二)源码解析之load()
文章目录 一.前言 二.源码分析 1.load() Android Glide图片加载框架系列文章 Android Glide图片加载框架(一)基本用法 Android Glide图片加载框架(二)源 ...
- Android Glide图片加载框架(二)源码解析之with()
文章目录 一.前言 二.如何阅读源码 三.源码解析 1.with() Android Glide图片加载框架系列文章 Android Glide图片加载框架(一)基本用法 Android Glide图 ...
- Android Glide图片加载框架(一)基本用法
文章目录 一.前言 二.简介 三.基本用法 第一步:调用 Glide.with() 方法创建加载图片的实例 第二步:调用 load() 方法指定待加载的图片资源 第三步:调用 into() 方法绑定显 ...
最新文章
- CUDA功能和通用功能
- 两次结果的绝对差值_多图示例:如何呈现论文结果中的各种图表
- 异常 —— throws
- python教程:datetime与字符串互转
- 中移动正进行智能网关互通测试:下半年规模集采
- UE4中的字符串转换
- ios系统脚本服务器加速,提高iOS项目的编译速度
- python处理网页弹窗_Selenium2+Python自动化-处理浏览器弹窗(转载)
- (一二四)给类对象赋值、以及类对象的返回值
- Windows Xp sp2 升级为 sp3
- SPI通信协议_02
- Struts2 通配符不能使用问题
- 为什么哪些90后程序员年薪50万+,他们经历了啥?
- UE4 Text Render 中文字体制作
- 阿里-蚂蚁金服-一面电面-上海-java研发实习生
- LeetCode(力扣)_接雨水
- 国外云盘(如Rapidgator)免费下载姿势详解
- win10:强力删除文件
- 后台(11)——Servlet(3)
- Windows MongoDB 安装及配置