Picasso源代码分析:5、Picasso架构分析

在之前Volley的学习当中,我们始终跟随者Volley的架构图进行分析,了解到Volley整体上分为3层线程,UI线程负责将Reqeust添加到ReqeustQueue当中,CacheDispatcher负责将从DiskCache中获取Response,如果Cache Hit,则直接分发结果至UI线程,如果Cache Miss,那么就将Reqeust添加至NetworkQueue当中,然后NetworkDispatcher则从队列中获取任务病执行,最后在UI线程中将结果分发。详细的可以参看:《Volley源代码学习总结》。

那么Picasso呢?这段时间我们学习Picasso,发现去文档、注释确实要远远逊色于Volley,说实话Picasso的代码风格个人也并不是很喜欢。但不能否认,Picasso是一个设计的十分细致的工具库。那整体框架是怎么样的呢?我根据这几天的学习以及个人的理解,按照Volley的架构图风格,给Picasso画了一张架构图。

Picasso-整体架构

 

大体一看,感觉和Volley很相近,但其实两者有很多细微上的不同,这里我们先不多说,后面会写一篇文章来对比Picasso和Volley。

我们来仔细看一下这张图,我来用文字再描述一边其整体的设计:

我们以一个任务的执行流程来描述一下Picasso的工作流程流程,最初的分析可以参考《Picasso源代码分析:1、跟随代码的角度,当我们添加了一个任务,到底发生了什么?》,其中不同的线程所做的工作,我会用上图中对应的颜色进行标注:

Picasso.with(Context).load("http://www.baidu.com/img/bdlogo.png").into(imageview);
  1. 初始化Picasso,实例化其唯一的对象。
  2. 根据传入的Url、File、resource Id,构建ReqeustCreator对象
  3. 根据ReqeustCreator构建Request对象,同时根据Reqeust属性,尝试从Cache中访问数据
  4. Cache Hit,则通过回调,设置Target或者ImageView,完成该Reqeust
  5. 如果Cache Miss,那么则构建相应的Action,并提交到DispatcherThread当中。
  6. Dispatcher中的Handler接收到相应的Message,调用dispatcher.performSubmit(action)进行处理。
  7. 创建BitmapHunter对象,并提交到PicassoExecutorService线程池
  8. 再次检查Memory Cache中已经有缓存,如果Hit,则读取缓存中的Bitmap
  9. 如果Cache miss,则交给Action对应的ReqeustHandler进行处理,比如网络请求,或者从File读取图片
  10. 返回结果之后,通知Dispatcher中的Handler处理结果。
  11. DispatcherThread中将BitmapHunter的结果打包(batch),最快200ms打包一次。通知主线程HANDLER进行处理
  12. 主线程HANDLER接收打包的BitmapHunter,对最后的结果进行分发。

 

我觉得应该从Picasso中学习到的设计图形缓存库的几个注意的地方:

  • 异步执行:包括任务的调度分发,任务的执行。
  • 结果的分发:所有的任务其结果通过主线程进行分发。
  • 避免内存泄漏:在Dispatcher中,使用WeakHashMap保存当前任务。
  • 避免OOM:同一时刻,仅允许一张图片进行解码,进行Transformation。

 

 

 

About: happyhls


4 thoughts on “Picasso源代码分析:5、Picasso架构分析”

  1. 我想请教一下:我为Picasso设置了diskcache,如下Client client = new OkHttpClient();client.setCache(new Cache(路径,50*1024*1024));Picasso picasso = new Builder(this).downloader(new OkHttploader(client)).build();picasso.setIndicatorsEnabled(true);加载图片后查看sd卡也有缓存的文件,程序中也有图片的三角是蓝色的,但是我却感觉很多缓存过了但是仍从网络加载,我想问问他的加载方式是否是内存、外存、网络这个顺序加载的?

    1. Hi,参见BitmapHunter.java中的hunt()方法(https://github.com/happyhls/Picasso-MyComments/blob/master/src/com/squareup/picasso/BitmapHunter.java),其中图片获取部分的代码,最开始是这样的。//如果不跳过MemoryCache,那么则尝试从MemoryCache获取 if (!skipMemoryCache) { bitmap = cache.get(key); if (bitmap != null) { stats.dispatchCacheHit(); loadedFrom = MEMORY; if (picasso.loggingEnabled) { log(OWNER_HUNTER, VERB_DECODED, data.logId(), “from cache”); } return bitmap; } }也就是说,会首先尝试cache方法中的get(key)方法来从Cache中获取,如果成功,则会直接将图片返回,如果不成功,会重新从网络获取。你可以从这个地方检查一下,或者debug,查看一下cache获取的图片有没有成功。

    1. Hi,这个问题我之前也看过,貌似Picasso不支持自定义的Diskcache,其Cache的实现主要依赖于其使用的Http Client,默认默认情况下使用的是OkHttpClient的内置缓存。可以参考:http://stackoverflow.com/questions/23280242/using-picasso-with-custom-disk-cache,http://stackoverflow.com/questions/23978828/using-disk-caching-in-picasso-android-lib,http://stackoverflow.com/questions/18944773/how-to-implement-my-own-disk-cache-with-picasso-library-android

发表评论

电子邮件地址不会被公开。 必填项已用*标注