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图片缓 ...
随机推荐
- 习题9-5 UVA 242
Stamps and Enovelope Size 题意: 给你最多贴S张邮票.有N个邮票集合,每个集合有不同的面值.问哪个集合的最大连续邮资最大,输出最大连续邮资和集合元素. 如果不止一个集合结果相 ...
- AR934X built-in switch链路检测问题及处理方法
1 问题 在使用QSDK平台配合QCA9531方案时,碰到过2个实在无解的问题,其一:将有线口连接到其它傻瓜交换机上,然后通过无线或另一个有线口登录的设备上,执行ifconfig ethx down, ...
- MySql查询不区分大小写解决方案(两种)
当我们输入不管大小写都能查询到数据,例如:输入 aaa 或者aaA ,AAA都能查询同样的结果,说明查询条件对大小写不敏感. 解决方案一: 于是怀疑Mysql的问题.做个实验:直接使用客户端用sql查 ...
- JS运行机制之 Event Loop 的思考
先举个栗子,如下: for (var i = 0; i < 5; i++) { setTimeout(function() { console.log('i: ',i); //一秒之后输出几乎没 ...
- SQL执行SQL语句提示 "内存不足"(insufficient memory....)的解决方法
由于本地执行的sql script的文件太大但是本地sql的运行内存有限,当我在MSSql的工具上运行这份178M左右的脚本的时候 它会提示 如下错误(Insufficient memory to c ...
- try_files 居然有这种用法
try_files 参考:https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ Use the tr ...
- JDBC线程池创建与DBCP源码阅读
创建数据库连接是一个比较消耗性能的操作,同时在并发量较大的情况下创建过多的连接对服务器形成巨大的压力.对于资源的频繁分配﹑释放所造成的问题,使用连接池技术是一种比较好的解决方式. 在Java中,连接池 ...
- [extjs5学习笔记]第三十八节 sencha CMD 6.0.0.220版本安装
本文地址:http://blog.csdn.net/sushengmiyan/article/details/46740381 简介 sencha cmd 6安装过程不需要UAC控制了对于widnow ...
- 【SSH系列】Hibernate映射 -- 继承映射
开篇前言 在前面的博文中,小编介绍了hibernate中的映射,一对一,一对多,多对多,单向,双向等,今天这篇博文,小编主要来介绍一下hibernate中的继承映射,小伙伴都知道在C#中,如果想要实现 ...
- CountDownLatch使用
分享牛原创,CountDownLatch类的使用,CountDownLatch是一个工具类,运行主线程开启子线程的时候,子线程还没有结束的时候,主线程可以一直等待,直到初始化的现成的计数器count为 ...
