《Picasso源码学习》

前言

  • 俗话说男儿有泪不轻弹,都26了,因为工作上的原因,有委屈,有压力,有不足,有外因,前几天自己在回家的路上,还是没忍住,人生最难过的事,莫过于别人对你失去信任。
  • 纸上得来终觉浅, 绝知此事要躬行。Picasso, Glide , Fresco 都使用过, 那我就会了吗 。源码解析,也看过很多写的很好的博客, 那我就深刻理解了吗? no , 这次教训太深刻了。
  • 哎, 不提了。 这次项目虽然有一定诸如时间紧,任务重,压力大,团队协作等外因, 但自己还是有问题的 。 哎,经验教训啊, 真是如履薄冰 , 再也不敢不细想就去写代码了。

正文

  • 简单用法就不说了,网上很多案例,还是按照常规,先上类图,看每个类的业务,这个是学习一个库的捷径吧,现在再我看来。
  • 在阅读源码之前,我想先明确一下,阅读这个源码的目的是什么,这样才能深刻理解,以及耐心看下去。
    1.picasso的常规用法,只是教会了大家如何使用加载图片,但如果我要二次使用picasso已加载图片了,那你得了解他的加载以及缓存机制,才知道从哪里如何去取,也不会像我这次一样,去瞎搞。因此,此行目的之一,就是清楚掌握如何从Picasso中获取图片,如果你觉得不是picasso.with(context).load(url).get()就了事了吗,那你肯定跟我之前一样too young too naive
    2.理清作者设计整个库的思路,方便我们自己的业务代码设计,以及封装。
    3.作者使用的设计模式等技巧,来实现封装具体的业务。这两点,我觉得中级以上的程序员,都应该有这个意识吧,对于初级一点的就不要求了

这里写图片描述
1. 接下来就一个类一个类的分析。
2. picasso:
1.首先它是一个单例模式 , 并且使用builder模式来构建自己的参数

2.类里面包含的
**Class**: BitmapHunter , Action , RequestHandler , Dispatcher , Stats
**Interface** : RequestTransformer , Listener , Cache
**static class**:  Builder , CleanupThread
**enum** : LoadedFrom 表示从哪里加载图片, Priority 表示优先等级

3.我们在来看看builder里面构建的参数,
**Context** 上下文,毫无悬念
**Downloader** 接口,
            1.一个从缓存or网络加载外部资源图片的机制,load(),shutdown() , 
            2.**Response** 内部类,里面包含InputStream , Bitmap , 看命名直译就是与图片资源相关的 , 很重要 的 里面有**getBitmap()**这个方法 ,到这里,我们可以猜测,Picasso加载图片有可能可以从Downloader参数里面获取
            3.**ExecutorService** 线程池,无须赘述,可以猜测这个是用来构建加载图片的
            4.**Cache** 接口:作者很用心就描述A memory cache for storing the most recently used images,内存缓存,可以从中获取近期加载的图片。很重要的,同样里面有get,set获取图片,设置缓存的方法。我们要从Picasso获取下载的图片,也有可能从这里直接获取缓存图片。
            5.**Listener** 接口:onImageLoadFailed这个方法,从命名可以看出,是加载图片失败的回调
            6.**RequestTransformer** 接口transformRequest(),转换请求,以及获取当前的请求。
            7.**List\<RequestHandler\>** 一个抽象类集合。
            RequestHandler是做什么的呢? 作者这里也说了,是可以通过去继承Picasso用其他去加载图片,而这些方法是原本这个库不支持的。
            里面的参数:静态内部类**Result**,这个内部类就很关键了,作者说了,这个返回结果都会保存在这个Result里面,这个离我们目标1很接近了, 也就是说,**请求返回的bitmap就在这个Result里面**。
            **Result**的参数:
                **LoadedFrom**:Picasso枚举状态,从哪里加载图片
                **Bitmap**:请求返回的bitmap
                **InputStream** : 无须赘述
            8.**Bitmap.Config**:无须赘述
  1. 看完整个Picasso类,可能我们对他的一些参数属性有一定的了解了,但是它如何加载图片,如何保存这一套业务,我们还是不是很清晰。这就得返回类图去理一下业务逻辑,顺着作者的思维,去看代码,而不是盲目的去看代码。
    其实Picasso里面还有一些重要的参数或者类,之前是遗漏掉的,不过没关系我们接下来顺着他的业务逻辑,继续看下去。自然而然之前遗漏的地方就能回顾到。

  2. Picasso一般在使用的时候,都是Picasso.with(context).load(url)…..。再去做图片处理业务上的操作,那这里就有两个问题了,1.Picasso内部类builder构建参数是什么时候调用的,知道builder模式都应该清楚。其实是在构建单例模式的时候,调用builder。build()构建的Picasso对象。2.Picass.with(context).load(url)返回的是一个RequestCreator。

  3. RequestCreator :在没看代码之前,我猜测,Picasso主要业务的实现应该在这里吧。首先我们还是来先看一下这个类的构成。Fluent API for building an image download request ,通过注释可以理解, 这个是类是用来构建一次下载请求的。

    1. 首先里面有2个参数,Picasso , Request.Builder ,他不会去持有Picasso 。
    2. 其实这个类里面,有我们平常很熟悉的使用Picasso加载图片的一些方法,比如placeholder(),resize(),fit()….但里面有我们平常很少使用,但比较重要的方法, into(@NonNull Target target) 在任意view加载该图片,而仅仅非ImageView, RequestCreator transform(@NonNull Transformation transformation) ,对请求图片进行处理在返回RequestCreator 进行加载。但必须注意的是除了get()返回一个bitmap是在主线程同步进行处理的,其他两个方法都是异步操作,为了避免卡顿,我们一般都是采用异步的方式去获取图片,很少使用get()这个方式去同步获取图片进行操作,这也是为什么我之前说如果你觉得不是picasso.with(context).load(url).get()就了事了吗,那你肯定跟我之前一样too young too naive
  4. 接着往下,因为RequestCreator去下载图片的时候会createRequest返回一个Request,那我们来看看Request到底做了什么。

  5. Request: request 使用builder模式来实现的,里面包含了要请求目标bitmap的uri以及config(也可以transform()成我们自己想要效果的的图片)

  6. 到了这一步,我们基本上捋清楚了Picasso在into(Target)之前初始化各项参数的准备工作,picasso.with(context).load(url).reseize().transform()……,现在就该关心一下下载业务是如何实现的了。Picasso.into()到target,首先会检查缓存中是否有目标图片,没有的话才会去下载。我们从7可知道,目标Bitamp的相关请求参数被封装在Request这个类里面,因此
    Action action =
    new ImageViewAction(picasso, target, request, memoryPolicy, networkPolicy, errorResId,
    errorDrawable, requestKey, tag, callback, noFade);
    picasso.enqueueAndSubmit(action);
    这段就是下载的代码。

  7. Action :一看上述表达式,就是一个接口或者抽象类。果不其然,这个类关注两个抽象方法即可,其他都是参数变量。
    abstract void complete(Bitmap result, Picasso.LoadedFrom from); 可以很清楚的知道complete()这个方法是最后获得图片的方法,接下来只需要看继承这个Aticon的子类如何实现complete这个操作即可。

    abstract void error();

  8. Dispatcher:在into(Target) 最后一步会调用dispatcher.dispatchSubmit(action); 这个类里面持有ExecutorService,Downloader,Handler这几个关键变量来实现下载,performSubmit()这个方法来具体实现,BitmapHunter , PicassoExecutorService这个是线程池

  9. BitmapHunter : 这是个线程,通过runnable()里面的hunt()方法去下载图片,requestHandler.load 为下一步请求的数据 。

  10. RequestHandler:可以理解为实施操作的类为RequestHandler,那首先我们还是来看看这个类的属性和参数、
    1.首先是一个静态内部类,Result , 从类里面的参数和作者的注释represents the result of a call,我们可以清楚的知道返回的结果在Result里面。Result类很简单,就是一些get,set方法
    2.其次就是里面有个重要的抽象方法,load() ,这一看就清楚了,这个handler是个抽象的父类,具体的业务肯定在子类实现。果不其然,RequestHandler是 abstract。并且该方法返回的是一个Result,那么就可以很清晰的理清了,接下来我们去看他4个子类分别实现load()方法即可。

  11. OkHttpDownloader和OkHttp3Downloader,UrlConnectionDownloader:最后来看看网络下载如何实现即可,这个类实现了Downloader接口。主要看load方法即可

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值