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图片缓 ...
随机推荐
- 2015 多校联赛 ——HDU5372(树状数组)
Sample Input 3 0 0 0 3 0 1 5 0 1 0 0 1 1 0 1 0 0 Sample Output Case #1: 0 0 0 Case #2: 0 1 0 2 有0, ...
- bzoj 2783: [JLOI2012]树
Description 在这个问题中,给定一个值S和一棵树.在树的每个节点有一个正整数,问有多少条路径的节点总和达到S.路径中节点的深度必须是升序的.假设节点1是根节点,根的深度是0,它的儿子节点的深 ...
- SPOJ NSUBSTR
You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...
- 从零开始搭建口袋妖怪管理系统(2)-借助ngRoute实现详情页面跳转
一.目标 上一次我们用Angular1.x完成了简单的口袋妖怪展示列表页面,现在我们想要了解口袋妖怪更多的信息,但是发现原有单行表格可能容纳不下口袋妖怪的所有信息,所以现在我们需要一个口袋妖怪详情界面 ...
- Java访问修饰符及其访问控制
java中的访问修饰符,可以看成是人的秘密分享级别.private 个人秘密 ,protected 家族秘密,default(不写修饰符)社区(邻居)秘密(在一个包下的能访问),public 社会秘密 ...
- spring基本原理
作者:王奕然链接:https://www.zhihu.com/question/21346206/answer/101789659来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- 对于DFT频谱泄漏问题的研究
问题简介: 对于频率为fs的正弦序列,它的频谱应该只是在fs处有离散谱.但是,在实际利用DFT求它的频谱时,对时域做了截断,结果使信号的频谱不只是在fs处有离散谱,而是在以fs为中心的频带范围内都有谱 ...
- jquery 实现图片无缝向左滚动
<script type="text/javascript" src="_pub/Script/jquery.js"></script> ...
- Comparators.sort (转载)
Comparator是个接口,可重写compare()及equals()这两个方法,用于比价功能:如果是null的话,就是使用元素的默认顺序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f, ...
- 一些重要的计算机网络协议(IP、TCP、UDP、HTTP)
一.计算机网络的发展历程 1.计算机网络发展 与其说计算机改变了世界,倒不如说是计算机网络改变了世界.彼时彼刻,你我都因网络而有了交集,岂非一种缘分? 计算机与网络发展大致经历如下过程:
