Android 图片加载框架Picasso

一:介绍
Picasso 是Square 公司开源的Android 端的图片加载和缓存框架
1.增加依赖:目前github上的版本2.7

在app下的build.gradle下增加依赖

implementation 'com.squareup.picasso:picasso:2.5.2'

二:应用
1.根本应用

Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher).into(imageView);//with下传递的是Context//load下有4个重载办法,传递别离是url加载一个以Uri门路的图片,File加载File中图片,String ,resourceId加载本地资源的图片//placeholder是加载一个占位图//into加载到控件中,也能够是实现了Target j接口的自定义View。


into办法的一些源码

public void into(Target target) {    long started = System.nanoTime();    //查看线程    //先查看主否在主线程运行,如果不是在主线程就会抛出一个应该在主线程运行的异样    checkMain();    if (target == null) {      throw new IllegalArgumentException("Target must not be null.");    }    if (deferred) {      throw new IllegalStateException("Fit cannot be used with a Target.");    }//判断是否加载url//data.hasImage():这里的data是在之前初始化的Request.Builder对象,它外面蕴含url地址,resourceId和默认配置,这里是判断uri或resourceId是否为空为0,如果是的话就勾销imageview的申请:picasso.cancelRequest(target);    if (!data.hasImage()) {      picasso.cancelRequest(target);      target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() : null);      return;    }

2.占位符placeholder,error,noPlaceholder,noFade
们的我的项目中通常最罕用的就是加载网络图片,然而因为网络环境的差别,有时侯加载网络图片的过程有点慢,这样界面上就会显示空ImageView什么也看不见,用户体验十分不好
placeholder
提供一张在网络申请还没申请实现时显示的图片,必须是本地图片

 Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher).into(imageView);

error
error 提供一张在加载图片出错的状况下显示的默认图

Picasso.with(this).load(url).error(R.mipmap.ic_launcher).into(imageView);

noPlaceholder
在调用into的时候明确通知你没有占位图设置。依据这个办法签名的解释是阻止View被回收的时候Picasso清空target或者设置一个利用的占位图。须要留神的是placeholder和noPlaceholder 不能同时利用在同一个申请上,会抛异样。

 Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).into(imageView);

noFade
无论你是否设置了占位图,Picasso 从磁盘或者网络加载图片时,into 显示到ImageView 都会有一个简略的渐入适度成果,让你的UI视觉效果更柔顺丝滑一点,如果你不要这个渐入的成果,就调用noFade办法。

Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).noFade().into(imageView);

3.设置图片的尺寸(resize),缩放(scale),裁剪(crop)
resize(int w,int h)
为了带宽、内存应用和下载速度等思考,服务端给咱们的图片的size 应该和咱们View 理论的size一样的,然而理论状况并非如此,服务端可能给咱们一些奇怪的尺寸的图片,咱们能够应用resize(int w,int hei) 来从新设置尺寸。

 Picasso.with(this).load(url).resize(200,200).noPlaceholder().error(R.mipmap.ic_launcher).noFade().into(imageView);

resize()办法承受的参数的单位是pixels,还有一个能够设置dp单位的办法,将你的尺寸写在dimens.xml文件中,而后用resizeDimen(int targetWidthResId, int targetHeightResId)办法

图片裁剪centerCrop()
Picasso 同样给咱们提供了一个办法,centerCrop,充斥ImageView 的边界,居中裁剪。

    Picasso.with(this).load(url).resize(400,200).noPlaceholder().error(R.mipmap.ic_launcher).noFade().centerCrop().into(imageView);

centerInside
下面的centerCrop是可能看不到全副图片的,如果你想让View将图片展现齐全,能够用centerInside,然而如果图片尺寸小于View尺寸的话,是不能充斥View边界的。

   Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).noFade().resize(400,200).centerInside().into(imageView);

fit
fit 是干什的呢?下面咱们须要用resize()来指定咱们须要的图片的尺寸,那就是说在程序中须要咱们计算咱们须要的尺寸(固定大小的除外),这样很麻烦,fit 办法就帮咱们解决了这个问题。fit 它会主动测量咱们的View的大小,而后外部调用reszie办法把图片裁剪到View的大小,这就帮咱们做了计算size和调用resize 这2步

       Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).noFade().resize(400,200).fit().centerInside().into(imageView);

图片旋转rotate()
在图片显示到ImageView 之前,还能够对图片做一些旋转操作,调用rotate(int degree)办法

  Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).noFade().rotate(180).into(imageView);

rotate(float degrees, float pivotX, float pivotY) 以(pivotX, pivotY)为原点旋转

 Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher).noFade().rotate(180,0,0).into(imageView);

4.转换器Transformation
Transformation 这就是Picasso的一个十分弱小的性能了,它容许你在load图片 -> into ImageView 两头这个过成对图片做一系列的变换。比方你要做图片高斯含糊、增加圆角、做度灰解决、圆形图片等等都能够通过Transformation来实现。
应用

 Picasso.with(this).load(url).noPlaceholder().error(R.mipmap.ic_launcher) .transform(new BlurTransformation(this))//这里增加了一个转换器实现高斯含糊 .into(imageView);

那么咱们如何实现这个转换器了BlurTransformation

public class BlurTransformation implements Transformation {    RenderScript rs;    public BlurTransformation(Context context) {        super();        rs = RenderScript.create(context);    }    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)    @Override    public Bitmap transform(Bitmap bitmap) {        // Create another bitmap that will hold the results of the filter.        Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);        // Allocate memory for Renderscript to work with        Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);        Allocation output = Allocation.createTyped(rs, input.getType());        // Load up an instance of the specific script that we want to use.        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));        script.setInput(input);        // Set the blur radius        script.setRadius(25);        // Start the ScriptIntrinisicBlur        script.forEach(output);        // Copy the output to the blurred bitmap        output.copyTo(blurredBitmap);        bitmap.recycle();        return blurredBitmap;    }    @Override    public String key() {        return "blur";    }}

5.同步/异步加载图片get(),fetch()
同步get()
很简略,同步加载应用get() 办法,返回一个Bitmap 对象

Bitmap bitmap=Picasso.with(this).load(url).get();//留神:应用同步办法不能放在主线程来做

异步fetch()
个别间接加载图片通过into显示到ImageView 是异步的形式,除此之外,还提供了2个异步的办法:

fetch() 异步形式加载图片
fetch(Callback callback) 异步形式加载图片并给一个回调接口

  Picasso.with(this).load(url).fetch(new Callback() {            @Override            public void onSuccess() {                            }            @Override            public void onError() {            }        });

fetch 办法异步加载图片并没有返回Bitmap,这个办法在申请胜利之后,将后果存到了缓存,包含磁盘和内存缓存。所以应用这种形式加载图片实用于这种场景:晓得稍后会加载图片,应用fetch 先加载缓存,起到一个预加载的成果。
6.缓存(Disk和Memory)
Picasso 有内存缓存(Memory)和磁盘缓存( Disk)
默认状况下,Picasso 内存缓存和磁盘缓存都开启了的,也就是加载图片的时候,内存和磁盘都缓存了,然而有些时候,咱们并不需要缓存,比如说:加载一张大图片的时候,如果再内存中保留一份,很容易造成OOM,这时候咱们只心愿有磁盘缓存,而不心愿缓存到内存,因而就须要咱们设置缓存策略了。Picasso 提供了这样的办法
形式一:memoryPolicy 设置内存缓存策略
NO_CACHE:示意解决申请的时候跳过查看内存缓存
NO_STORE: 示意申请胜利之后,不将最终的后果存到内存。

Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher).memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)//禁止内存缓存.into(imageView);

之前咱们也有应用skipMemoryCache来禁止内存缓存,然而如同当初新的没有用了

 Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher).skipMemoryCache().into(imageView);

那咱们就须要去看一下源码:

//看源码标注废除//其实他也是调用memoryPolicy,传递默认的NO_CACHE,NO_STORE  /**   * @deprecated Use {@link #memoryPolicy(MemoryPolicy, MemoryPolicy...)} instead.   */  @Deprecated public RequestCreator skipMemoryCache() {    return memoryPolicy(NO_CACHE, NO_STORE);  }  /**   * Specifies the {@link MemoryPolicy} to use for this request. You may specify additional policy   * options using the varargs parameter.   */  public RequestCreator memoryPolicy(MemoryPolicy policy, MemoryPolicy... additional) {  //不能为空,空异样    if (policy == null) {      throw new IllegalArgumentException("Memory policy cannot be null.");    }    this.memoryPolicy |= policy.index;    //不能为空,异样,故2个参数不能为空    if (additional == null) {      throw new IllegalArgumentException("Memory policy cannot be null.");    }    if (additional.length > 0) {      for (MemoryPolicy memoryPolicy : additional) {        if (memoryPolicy == null) {          throw new IllegalArgumentException("Memory policy cannot be null.");        }        this.memoryPolicy |= memoryPolicy.index;      }    }    return this;  }//依据源码查看memoryPolicy办法的参数不能为空

那么咱们看一下硬盘缓存
形式二:networkPolicy 设置磁盘缓存策略
NO_CACHE: 示意解决申请的时候跳过解决磁盘缓存
NO_STORE:示意申请胜利后,不将后果缓存到Disk,然而这个只对OkHttp无效。
OFFLINE: 这个就跟 下面两个不一样了,如果networkPolicy办法用的是这个参数,那么Picasso会强制这次申请从缓存中获取后果,不会发动网络申请,不论缓存中是否获取到后果。

Picasso.with(this).load(url).placeholder(R.mipmap.ic_launcher).networkPolicy(NetworkPolicy.NO_CACHE).into(imageView);

7.Debug和日志
Picasso 有内存缓存和磁盘缓存,先从内存获取,没有再去磁盘缓存获取,都没有就从网络加载,网络加载是比拟低廉和耗时的。因而,作为一个开发者,咱们往往须要加载的图片是从哪儿来的(内存、Disk还是网络),Picasso让咱们很容易就实现了。只须要调用一个办法setIndicatorsEnabled(boolean)就能够了,它会在图片的左上角呈现一个带色块的三角形标示,有3种颜色,绿色示意从内存加载、蓝色示意从磁盘加载、红色示意从网络加载。

日志
Picasso,能够打印一些日志,比方一些要害办法的执行工夫等等,咱们只须要调用setLoggingEnabled(true)办法,而后App在加载图片的过程中,咱们就能够从logcat 看到一些要害的日志信息。

三:Picasso总结
1.Picasso 是下载图片而后缓存残缺的大小到本地,比如说图片的大小是1080p的,之后如果我须要同一张图片,就会返回这张 full size 的,如果我须要resize,也是对这种 full size 的做 resize。
2.Picasso 则是用的 ARGB _8888的设定。Glide 默认是用的 RGB_565 的设定
3.加载工夫问题(当从网络加载Picasso快一些,当从内存加载Glide快一些)
当尝试加载一个图片的时候,两个库都会采纳先从缓存中读取,如果缓存中没有,再去下载的做法。
理论试验中,Picasso 会比 Glide 快一点。猜想可能的起因还是因为之前讲到的缓存机制导致,因为Picasso 是间接把图加载到内存中,而 Glide 则须要扭转图片大小再加载到内存中去。这个应该是会消耗肯定的工夫。

然而,当加载图片从内存中的时候,Glide 则比 Picasso 要快。其原理还是因为缓存机制的区别。因为Picasso 从缓存中拿到的图片,还要先去 resize 后,而后设定给 imageView,然而 Glide 则不须要这样。
4.Picasso.with(这里只能传入上下文) .
Glide.with,前面能够传入上下文,activity实例,FragmentActivity实例,Fragement.传入的对象要比前者多.

结尾:如果我看得更远一点的话,是因为我站在伟人的肩膀上