picasso图片缓存框架
picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能。
picasso使用简单,如下
- Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
主要有以下一些特性:
- 在adapter中回收和取消当前的下载;
- 使用最少的内存完成复杂的图形转换操作;
- 自动的内存和硬盘缓存;
- 图形转换操作,如变换大小,旋转等,提供了接口来让用户可以自定义转换操作;
- 加载载网络或本地资源;
代码分析
Cache,缓存类
- this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
最后一个参数的解释:
- private void trimToSize(int maxSize) {
- while (true) {
- String key;
- Bitmap value;
- synchronized (this) {
- if (size < 0 || (map.isEmpty() && size != 0)) {
- throw new IllegalStateException(getClass().getName()
- + ".sizeOf() is reporting inconsistent results!");
- }
- if (size <= maxSize || map.isEmpty()) {
- break;
- }
- Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator()
- .next();
- key = toEvict.getKey();
- value = toEvict.getValue();
- map.remove(key);
- size -= Utils.getBitmapBytes(value);
- evictionCount++;
- }
- }
- }
Request,操作封装类
- public interface Transformation {
- /**
- * Transform the source bitmap into a new bitmap. If you create a new bitmap instance, you must
- * call {@link android.graphics.Bitmap#recycle()} on {@code source}. You may return the original
- * if no transformation is required.
- */
- Bitmap transform(Bitmap source);
- /**
- * Returns a unique key for the transformation, used for caching purposes. If the transformation
- * has parameters (e.g. size, scale factor, etc) then these should be part of the key.
- */
- String key();
- }
当操作封装好以后,会将Request传到另一个结构中Action。
Action
- @Override
- public void complete(Bitmap result, Picasso.LoadedFrom from) {
- if (result == null) {
- throw new AssertionError(String.format(
- "Attempted to complete action with no result!\n%s", this));
- }
- ImageView target = this.target.get();
- if (target == null) {
- return;
- }
- Context context = picasso.context;
- boolean debugging = picasso.debugging;
- PicassoDrawable.setBitmap(target, context, result, from, noFade,
- debugging);
- if (callback != null) {
- callback.onSuccess();
- }
- }
有了加载任务,具体的图片下载与解析是在哪里呢?这些都是耗时的操作,应该放在异步线程中进行,就是下面的BitmapHunter。
BitmapHunter
- @Override
- public void run() {
- try {
- Thread.currentThread()
- .setName(Utils.THREAD_PREFIX + data.getName());
- result = hunt();
- if (result == null) {
- dispatcher.dispatchFailed(this);
- } else {
- dispatcher.dispatchComplete(this);
- }
- } catch (IOException e) {
- exception = e;
- dispatcher.dispatchRetry(this);
- } catch (Exception e) {
- exception = e;
- dispatcher.dispatchFailed(this);
- } finally {
- Thread.currentThread().setName(Utils.THREAD_IDLE_NAME);
- }
- }
- abstract Bitmap decode(Request data) throws IOException;
- Bitmap hunt() throws IOException {
- Bitmap bitmap;
- if (!skipMemoryCache) {
- bitmap = cache.get(key);
- if (bitmap != null) {
- stats.dispatchCacheHit();
- loadedFrom = MEMORY;
- return bitmap;
- }
- }
- bitmap = decode(data);
- if (bitmap != null) {
- stats.dispatchBitmapDecoded(bitmap);
- if (data.needsTransformation() || exifRotation != 0) {
- synchronized (DECODE_LOCK) {
- if (data.needsMatrixTransform() || exifRotation != 0) {
- bitmap = transformResult(data, bitmap, exifRotation);
- }
- if (data.hasCustomTransformations()) {
- bitmap = applyCustomTransformations(
- data.transformations, bitmap);
- }
- }
- stats.dispatchBitmapTransformed(bitmap);
- }
- }
- return bitmap;
- }
可以看到,在decode生成原始bitmap,之后会做需要的转换transformResult和applyCustomTransformations。最后在将最终的结果传递到上层dispatcher.dispatchComplete(this)。
Dispatcher任务调度器
Dispatcher内有一个HandlerThread,所有的请求都会通过这个thread转换,也就是请求也是异步的,这样应该是为了Ui线程更加流畅,同时保证请求的顺序,因为handler的消息队列。
外部调用的是dispatchXXX方法,然后通过handler将请求转换到对应的performXXX方法。
例如生成Action以后就会调用dispather的dispatchSubmit()来请求执行,
- void dispatchSubmit(Action action) {
- handler.sendMessage(handler.obtainMessage(REQUEST_SUBMIT, action));
- }
handler接到消息后转换到performSubmit方法
- void performSubmit(Action action) {
- BitmapHunter hunter = hunterMap.get(action.getKey());
- if (hunter != null) {
- hunter.attach(action);
- return;
- }
- if (service.isShutdown()) {
- return;
- }
- hunter = forRequest(context, action.getPicasso(), this, cache, stats,
- action, downloader);
- hunter.future = service.submit(hunter);
- hunterMap.put(action.getKey(), hunter);
- }
这里将通过action得到具体的BitmapHunder,然后交给ExecutorService执行。
- public static Picasso with(Context context) {
- if (singleton == null) {
- singleton = new Builder(context).build();
- }
- return singleton;
- }
- public Picasso build() {
- Context context = this.context;
- if (downloader == null) {
- downloader = Utils.createDefaultDownloader(context);
- }
- if (cache == null) {
- cache = new LruCache(context);
- }
- if (service == null) {
- service = new PicassoExecutorService();
- }
- if (transformer == null) {
- transformer = RequestTransformer.IDENTITY;
- }
- Stats stats = new Stats(cache);
- Dispatcher dispatcher = new Dispatcher(context, service, HANDLER,
- downloader, cache, stats);
- return new Picasso(context, dispatcher, cache, listener,
- transformer, stats, debugging);
- }
在Picasso.with()的时候会将执行所需的所有必备元素创建出来,如缓存cache、执行executorService、调度dispatch等,在load()时创建Request,在into()中创建action、bitmapHunter,并最终交给dispatcher执行。
picasso图片缓存框架的更多相关文章
- Android图片缓存框架Glide
Android图片缓存框架Glide Glide是Google提供的一个组件.它具有获取.解码和展示视频剧照.图片.动画等功能.它提供了灵活的API,帮助开发者将Glide应用在几乎任何网络协议栈中. ...
- android图片缓存框架Android-Universal-Image-Loader
http://blog.csdn.net/king_is_everyone/article/details/34107081 最近跟同学们做了一个创业项目,其实跟以前做项目不同,以前大多数都是做web ...
- iOS图片缓存框架SDWebImage
本文转发至: http://blog.csdn.net/uxyheaven/article/details/7909373 http://www.cocoachina.com/ios/20141212 ...
- android图片缓存框架Android-Universal-Image-Loader(二)
http://blog.csdn.net/king_is_everyone/article/details/35595515 这篇打算直接告诉大家怎么用吧,其实这个也不是很难的框架,大致使用过程如下: ...
- 通过案例快速学会Picasso图片缓存库
picasso是Square公司开源的一个Android图形缓存库,官网地址http://square.github.io/picasso/,可以实现图片下载和缓存功能. 下载地址:ht ...
- Android图片缓存之初识Glide
前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...
- 安卓高级 Android图片缓存之初识Glide
前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...
- Android图片缓存之初识Glide(三)
前言: 前面总结学习了图片的使用以及Lru算法,今天来学习一下比较优秀的图片缓存开源框架.技术本身就要不断的更迭,从最初的自己使用SoftReference实现自己的图片缓存,到后来做电商项目自己的实 ...
- Android图片缓存之Bitmap详解
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...
随机推荐
- bzoj1071[SCOI2007]组队
1071: [SCOI2007]组队 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2472 Solved: 792[Submit][Status][ ...
- hdu5634 BestCoder Round #73 (div.1)
Rikka with Phi Accepts: 5 Submissions: 66 Time Limit: 16000/8000 MS (Java/Others) Memory Limit: ...
- JavaBean实现用户登陆
本文简单讲述使用javabean实现用户登录,包括用户登录,注册和退出等. 系统结构图 2.数据库表 create table P_USER ( id VARCHAR2(50) not n ...
- PTA 邻接表存储图的广度优先遍历(20 分)
6-2 邻接表存储图的广度优先遍历(20 分) 试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(V ...
- @Transient 理解
transient使用小结 1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问. 2)transient关键字只能修饰变量,而不能修饰方法和类.注意 ...
- windows下cmd中命令操作
windows下cmd中命令: cls清空 上下箭头进行命令历史命令切换 ------------------------------------------------------------- ...
- scratch写的图灵机
大多数人对于scratch不感冒,因为觉得这是孩子玩的.的确,积木的方式不适合专业程序员写代码,然而别小看scratch,怎么说,它也是图灵完备的.而且,过程支持递归,虽然带不了返回值. 虽然计算速度 ...
- PHP MySQL 创建数据表
PHP 创建 MySQL 表 一个数据表有一个唯一名称,并有行和列组成. 使用 MySQLi 和 PDO 创建 MySQL 表 CREATE TABLE 语句用于创建 MySQL 表. 我们将创建一个 ...
- 详解BLE 空中包格式—兼BLE Link layer协议解析
BLE有几种空中包格式?常见的PDU命令有哪些?PDU和MTU的区别是什么?DLE又是什么?BLE怎么实现重传的?BLE ACK机制原理是什么?希望这篇文章能帮你回答以上问题. 虽然BLE空中包(pa ...
- AbstractQueuedSynchronizer源码解读
1. 背景 AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是Doug Lea大师创作的用来构建锁或者其他同步组件(信号量.事件等) ...
