使用:

Picasso.with(this)
.load("http://imgstore.cdn.sogou.com/app/a/100540002/467502.jpg")
.into((ImageView) findViewById(R.id.ivImage)); (1),首先进入Picasso.with(this):

创建一个Picasso类型单例singleton, 接着进入Builder构造函数:

这里是通过传入的context获取全局的context,主要是为了防止内存泄漏, 接着我们看build方法:

先简要分析一下这里的主流程,后面再进行详细分析:

首先创建一个Downloader,看名字猜测应该是用于下载图片的; 接着创建一个LruCache用于图片的内存缓存; 然后创建一个ExecutorService子类PicassoExecutorService的线程池对象,用于执行具体的下载图片任务; 然后再创建一个请求转换器RequestTransformer对象(具体干嘛的目前还不知道,看名字猜测是做一些什么装换); 接着创建一个Stats对象(具体干嘛的目前还不知道,看名字猜测和状态有关); 然后再创建一个分发器Dispatcher对象,用于分发多个图片的请求到线程池里的线程去执行;
最后,创建了一个Picasso对象返回.
(2)进入load函数:

首先判断图片路径是否为null,是的话则创建一个uri为null的请求生成器RequestCreator(应该是用来生成图片加载请求的);如果非null但url长度为0,则直接抛出异常;否则进入load的重载方法:

根据图片路径path解析出相应的uri构建一个RequestCreator对象返回.

(3)接下来看into方法,最终会调用into(ImageView target, Callback callback)方法:

首先通过checkMain方法检查是否在主线程调用,不是在主线程则直接抛出异常(代码略),然后判断imageView是否为空,为空则抛出异常.

 这段代码是判断是否要延期处理,我们没有延期,直接跳过.

这里首先根据开始时间创建一个请求,根据请求创建一个请求的key;
然后根据内存缓存策略判断是否需要从内存中读取缓存图片,默认需要;
如果需要从内存读取,则从内存读取图片,读取出来的图片如果非空,则返回,不用发起网络请求了;
如果回调接口非空,则回调成功(我们这里是null,不管).

先判断是否设置了占位图片,如果设置了则先显示占位图;
接着创建一个Action对象,然后将这个action对象加入队列并提交到线程池执行. 接着我们看看enqueueAndSubmit方法具体干了啥:

首先获取上一步创建Action时设置的ImageView对象target, 如果target非空并且在Map对象targetToAction里已经存在这个action,则取消已经存在的请求,并且将这个action存入map;
然后提交执行这个Action.

分发器将这个action进行分发,其实就是通过handler发送一条REQUEST_SUBMIT类型的消息,接着handler收到这条消息后进行处理.

首先判断Set集合pausedTags里是否包含action的key,这里初次请求是不包含的,略过;
接着在Map对象里通过action的key获取BitmapHunter,初次请求这里获取的位空.

首先判断线程池是否关闭,如果关闭了则返回;

接着通过forRequest方法创建一个BitmapHunter对象;

最后将这个BitmapHunter(实现了Runnable接口,具体这个runnable干什么我们后面分析)提交到线程池执;
最后它存入map,下次就可以直接取图片了.

下面我们详细分析:
在forRequest方法里通过picasso.getRequestHandlers()获取请求处理器list,这些处理器如下:

判断请求处理器能否处理本次请求,能处理则构造相应的BitmapHunter.

具体如何判断,我们看看RequestHandler的canHandleRequest方法,这里以NetworkRequestHandler为例:

主要是通过scheme进行判断, 所以这里返回的RequestHandler就是NetworkRequestHandler.

接着我们看看这个BitmapHunter具体干了些什么:
这里主要是通过hunt方法获取图片,通过获取的结果进行分发,我们继续看看hunt方法干了啥:

这里是从内存里读取图片的相关操作.

这里是根据网络策略进行图片读取,这里的OFFLINE是disk only,接着我们看看具体怎么读取?

这里通过downloader进行加载图片(具体如何加载下面说),然后返回.

先是根据缓存策略设置缓存控制(http缓存),接着使用OkHttpClient加载图片.

貌似没有磁盘缓存? 我们看看Downloader的构建过程:

在构建Downloader的时候,设置了默认的缓存路径,使用http缓存代替disk缓存.(该库和其他下载图片库的主要区别之一:使用4.0+系统上的HTTP缓存来代替Disk磁盘缓存)
关于http缓存,请参考以下文章:

HTTP 协议缓存机制详解

OKHTTP之缓存配置详解



 



 


源码分析: 图片加载框架Picasso源码分析的更多相关文章

  1. 第一次源码分析: 图片加载框架Picasso源码分析

    使用: Picasso.with(this) .load("http://imgstore.cdn.sogou.com/app/a/100540002/467502.jpg") . ...

  2. Android 图片加载框架Picasso基本使用和源码完全解析(巨细无比)

    写在之前 原本打算是每周更新一篇博文,同时记录一周的生活状态,但是稍微工作忙一点就顾不上写博客了.悲催 还是说下最近的状况,最近两周一直在接公司申请的计费点, 沃商店,银贝壳,微信等等,然后就是不停的 ...

  3. Android图片加载框架Picasso最全使用教程4

    通过前几篇的学习,我们已经对Picasso的加载图片的用法有了很深的了解,接下来我们开始分析Picasso为我们提供的其他高级功能及内存分析,Let’sGo ! Picasso进行图片的旋转(Rota ...

  4. Android图片加载框架Picasso最全使用教程3

    前面我们对Picasso的用法有了一定得了解,下面就分析一下一些特殊情况下,Picasso的用法. 调用.noFade() Picasso的默认图片加载方式有一个淡入的效果,如果调用了noFade() ...

  5. Android图片加载框架Picasso最全使用教程2

    前言 前面我们已经介绍了Picasso的基本用法及如何将一张图片加载到ImageView中,下面我们就利用Picasso在ListView中加载图片;Let’s Go! 一个ListView的简单应用 ...

  6. Android图片加载框架Picasso最全使用教程1

    Picasso介绍 Picasso是Square公司开源的一个Android图形缓存库 A powerful image downloading and caching library for And ...

  7. 图片加载框架Picasso解析

    picasso是Square公司开源的一个Android图形缓存库 主要有以下一些特性: 在adapter中回收和取消当前的下载: 使用最少的内存完成复杂的图形转换操作: 自动的内存和硬盘缓存: 图形 ...

  8. Android图片加载框架Picasso最全使用教程5

    在之前的四篇博客中,我们学习了所有的关于Picasso的主要方法,我们也对这个Picasso有了一个很深的认识,下面就主要对Picasso自身进行分析,这样的话,会让我们更了解Picasso的核心方法 ...

  9. Android图片加载框架之Picasso

    相信做Android开发的对Square公司一定不会陌生,大名鼎鼎的网络请求框架Retrofit就来源于它,今天学习的是该公司出品的图片加载框架Picasso. 项目地址 https://github ...

随机推荐

  1. macOS10.14 Mojave无法打开和预览jpg的解决方法

    分析:之所以会出现这样的问题.是因为你用了独显 而没有驱动核显导致的.想要预览正常只要用核显或者开启核显加速就OK了就可以正常预览了. 解决办法:换无核显的机型试试,比如MacPro6.1,iMac ...

  2. iScroll.js 向上滑动异步加载数据回弹问题

    iScroll是一款用于移动设备web开发的一款插件.像缩放.下拉刷新.滑动切换等移动应用上常见的一些效果都可以轻松实现. 现在最新版本是5.X,官网这里:http://iscrolljs.com/ ...

  3. Netty入门(一)之webSocket聊天室

    一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...

  4. Python 学习 第十三篇:数据的读写-文件、DataFrame、json

    Python的文件是一个重要的对象,使用open()函数来打开文件,创建文件对象,进行文件的读写操作.当数据用于交换信息时,通常需要把数据保存为有格式的文本数据,可以保存为有特定的行分隔符和列分隔符的 ...

  5. 分布式系统消息中间件——RabbitMQ的使用思考篇

    分布式系统消息中间件--RabbitMQ的使用思考篇 前言     前面的两篇文章分布式系统消息中间件--RabbitMQ的使用基础篇与分布式系统消息中间件--RabbitMQ的使用进阶篇,我们简单介 ...

  6. ESP8266的低功耗方案-睡眠模式

    在某些时候我们设计的产品可能不具备持久供电的环境,那通常会采用锂电池.干电池一类的轻便型的非持久性电源.当遇到这种情况时,产品的续航能力可能就会成用户评估产品的一个重要指标,加大电池容量当然是最为直接 ...

  7. 四、xadmin自定义插件1

    插件原理: Xadmin中每个页面都是一个AdminView对象返回的HTTPResponse结果. Xdamin插件所做的事情就是其实就是在AdminView执行过程中改变其执行逻辑或是改变其返回的 ...

  8. 如何让.net程序支持TLS1.2

    1.将.Net FrameWork设置成4.6以上版本 2.在需要的类中引入命名空间 using System.Net; 3.在程序调用接口(如支付)的地方,加一段代码即可 System.Net.Se ...

  9. 使用insert ignore来避免向数据库重复插入数据

    mysql中 insert ignore 的使用示例如下: INSERT IGNORE INTO `table_name` (`reportid`, `content`) VALUES (‘11111 ...

  10. Python-Django下载与基本命令

    1.下载Django: pip3 install django 2.创建一个django project django-admin.py startproject mysite 当前目录下会生成mys ...