图片加载框架-Picasso最详细的使用指南

写在前面

Android 中有几个比较有名的图片加载框架,Universal ImageLoader、Picasso、Glide和Fresco。它们各有优势,之前一直用的是ImageLoader 作项目中的图片加载,因为做者宣布ImageLoader 不会在更新了,所以新的项目打算换一个图片加载框架-Picasso, Picasso 是Square 公司开源的Android 端的图片加载和缓存框架。Square 真是一家良心公司啊,为咱们Android开发者贡献了不少优秀的开源项目有木有!像什么Rerefoit 、OkHttp、LeakCanary、Picasso等等都是很是火的开源项目。扯远了,回到正题,除了使用简单方便,Picasso还能自动帮咱们作如下事情:java

  • 处理Adapter 中ImageView的回收和取消下载。
  • 使用最小的内存 来作复杂的图片变换。好比高斯模糊,圆角、圆形等处理。
  • 自动帮咱们缓存图片。内存和磁盘缓存。

以上只是列出了Picasso 比较核心的几点,其实它的优势远远不止这些,接下来就看一下如何使用Picasso。android

Picasso-Android.png

本文目录

0,添加依赖
1, 加载显示图片
2,Placeholder & noPlaceholder & noFade
3, 设置图片尺寸(Resize)、缩放(Scale)和裁剪(Crop)
4,图片旋转Rotation()
5, 转换器Transformation
6,请求优先级
7,Tag管理请求
8,同步/异步加载图片
9,缓存(Disk 和 Memory)
10,Debug 和日志
11,Picasso 扩展git

正文

0. 添加依赖

要使用Picasso,首先咱们要添加版本依赖,去官网或者Github 看一下当前的最新版本(截止本文最新版本为2.5.2),而后在build.gradle中添加依赖:github

compile 'com.squareup.picasso:picasso:2.5.2'复制代码

1. 加载显示图片

将Picasso添加到项目以后,咱们就能够用它来加载图片了,使用方法很是简单:缓存

Picasso.with(this)
        .load("http://ww3.sinaimg.cn/large/610dc034jw1fasakfvqe1j20u00mhgn2.jpg")
        .into(mImageView);复制代码

只须要一行代码就完成了加载图片到显示的整个过程,链式调用,很是简洁,其实有三步,一次调用了三个方法:网络

  • with(Context) 获取一个Picasso单例,参数是一个Context上下文
  • load(String) 调用load 方法加载图片
  • into (ImageView) 将图片显示在对应的View上,能够是ImageView,也能够是实现了Target j接口的自定义View。

上面演示了加载一张网络图片,它还支持其它形式的图片加载,加载文件图片,加载本地资源图片,加载一个Uri 路径给的图片,提供了几个重载的方法:app

1, load(Uri uri) 加载一个以Uri路径给的图片框架

Uri uri = Uri.parse(ANDROID_RESOURCE + context.getPackageName() + FOREWARD_SLASH + resourceId)

Picasso.with(this).load(uri).into(mImageView);复制代码

2,load(File file) 加载File中的图片less

Picasso.with(this).load(file).into(mImageView);复制代码

3, load(int resourceId) 加载本地资源图片异步

Picasso.with(this).load(R.mipmap.ic_launcher).into(mImageView);复制代码

提醒:上面介绍了load的几个重载方法,加载不一样资源的图片,另外提醒注意一下load(String path)接受String 参数的这个方法,参数String 能够是一个网络图片url,也能够是file 路径、content资源 和Android Resource。看一下源码的注释。

/** * Start an image request using the specified path. This is a convenience method for calling * {@link #load(Uri)}. * <p> * This path may be a remote URL, file resource (prefixed with {@code file:}), content resource * (prefixed with {@code content:}), or android resource (prefixed with {@code * android.resource:}. * <p> * Passing {@code null} as a {@code path} will not trigger any request but will set a * placeholder, if one is specified. * * @see #load(Uri) * @see #load(File) * @see #load(int) * @throws IllegalArgumentException if {@code path} is empty or blank string. */
  public RequestCreator load(String path) {
    if (path == null) {
      return new RequestCreator(this, null, 0);
    }
    if (path.trim().length() == 0) {
      throw new IllegalArgumentException("Path must not be empty.");
    }
    return load(Uri.parse(path));
  }复制代码

要使用string 参数加载上面的几种资源,除了网络url,其它几种须要加上对应前缀,file文件路径前缀:file: , content 添加前缀:content: ,Android Resource 添加:android.resource:

2. placeholder& error & noPlaceholder & noFade

经过上面的第一步咱们就能够经过Picasso 加载图片了,咱们的项目中一般最经常使用的就是加载网络图片,可是因为网络环境的差别,有时侯加载网络图片的过程有点慢,这样界面上就会显示空ImageView什么也看不见,用户体验很是很差。其实之前用过ImageLoader的同窗都知道,ImageLoader 是能够设置加载中显示默认图片的,Picasso固然也给咱们提供了这个功能,这就是咱们要说的placeholder(占位图)。

1,placeholder
placeholder提供一张在网络请求尚未完成时显示的图片,它必须是本地图片,代码以下:

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .into(mImageView);复制代码

设置placeholder以后,在加载图片的时候,就能够显示设置的默认图了,提高用户体验。
2, error
和placeholder 的用法同样,error 提供一张在加载图片出错的状况下显示的默认图

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .into(mImageView);复制代码

3,noPlaceholder
这个方法的意思就是:在调用into的时候明确告诉你没有占位图设置。根据这个方法签名的解释是阻止View被回收的时候Picasso清空target或者设置一个应用的占位图。须要注意的是placeholder和noPlaceholder 不能同时应用在同一个请求上,会抛异常。

Picasso.with(this).load(URL)
                .noPlaceholder()
                .error(R.drawable.error_iamge)
                .into(mImageView);复制代码

4,noFade
不管你是否设置了占位图,Picasso 从磁盘或者网络加载图片时,into 显示到ImageView 都会有一个简单的渐入过分效果,让你的UI视觉效果更柔顺丝滑一点,若是你不要这个渐入的效果(没有这么坑爹的需求吧!!!),就调用noFade方法。

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .noFade()
                .into(mImageView);复制代码

3. 设置图片尺寸(Resize)、缩放(Scale)和裁剪(Crop)

1, Resize(int w,int h)
在项目中,为了带宽、内存使用和下载速度等考虑,服务端给咱们的图片的size 应该和咱们View 实际的size同样的,可是实际状况并不是如此,服务端可能给咱们一些奇怪的尺寸的图片,咱们可使用resize(int w,int hei) 来从新设置尺寸。

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .resize(400,200)
                .into(mImageView);复制代码

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

<dimen name="image_width">300dp</dimen>
 <dimen name="image_height">200dp</dimen>复制代码
Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .resizeDimen(R.dimen.image_width,R.dimen.image_height)
                .into(mImageView);复制代码

2,onlyScaleDown
当调用了resize 方法从新设置图片尺寸的时候,调用onlyScaleDown 方法,只有当原始图片的尺寸大于咱们指定的尺寸时,resize才起做用,如:

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .resize(4000,2000)
                .onlyScaleDown()
                .into(mImageView);复制代码

只有当原来的图片尺寸大于4000 x 2000的时候,resize 才起做用。
3,图片裁剪 centerCrop()
这个属性应该不陌生吧!ImageView 的ScaleType 就有这个属性。当咱们使用resize 来从新设置图片的尺寸的时候,你会发现有些图片拉伸或者扭曲了(使用ImageView的时候碰到过吧),我要避免这种状况,Picasso 一样给咱们提供了一个方法,centerCrop,充满ImageView 的边界,居中裁剪

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .resize(400,200)
                .centerCrop()
                .into(mImageView);复制代码

4,centerInside
上面的centerCrop是可能看不到所有图片的,若是你想让View将图片展现彻底,能够用centerInside,可是若是图片尺寸小于View尺寸的话,是不能充满View边界的。

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .resize(400,200)
                .centerInside()
                .into(mImageView);复制代码

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

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .into(mImageView);复制代码

使用fit 仍是会出现拉伸扭曲的状况,所以最好配合前面的centerCrop使用,代码以下:

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .centerCrop()
                .into(mImageView);复制代码

看一下对比图:
fit(会拉伸):

image_fit.png

fit & centerCrop (不会拉伸):

fit_centerCrop.png

注意:特别注意,
1,fit 只对ImageView 有效
2,使用fit时,ImageView 宽和高不能为wrap_content,很好理解,由于它要测量宽高。

4. 图片旋转Rotation()

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

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .rotate(180)
                .into(mImageView);复制代码

这个方法它是以(0,0)点旋转,可是有些时候咱们并不想以(0,0)点旋转,还提供了另一个方法能够指定原点:

  • rotate(float degrees, float pivotX, float pivotY) 以(pivotX, pivotY)为原点旋转
Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .rotate(180,200,100)
                .into(mImageView);复制代码

5. 转换器Transformation

Transformation 这就是Picasso的一个很是强大的功能了,它容许你在load图片 -> into ImageView 中间这个过成对图片作一系列的变换。好比你要作图片高斯模糊、添加圆角、作度灰处理、圆形图片等等均可以经过Transformation来完成。

来看一个高斯模糊的例子:

1,首先定义一个转换器继承 Transformation

public static class BlurTransformation implements Transformation{

        RenderScript rs;

        public BlurTransformation(Context context) {
            super();
            rs = RenderScript.create(context);
        }

        @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";
        }
    }复制代码

2, 加载图片的时候,在into 方法前面调用 transform方法 应用Transformation

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .transform(new BlurTransformation(this))
                .into(mBlurImage);复制代码

看一下效果图:

transformation.png

上面为原图,下面为高斯模糊图

是否是很强大,任何复杂的变换均可以经过Transformation 来作。

还不止于此,还有更强大的功能。能够在一个请求上应用多个Transformation

好比:我想先作个度灰处理而后在作一个高斯模糊图:

1, 度灰的Transformation

public static class GrayTransformation implements Transformation{

        @Override
        public Bitmap transform(Bitmap source) {
            int width, height;
            height = source.getHeight();
            width = source.getWidth();

            Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
            Canvas c = new Canvas(bmpGrayscale);
            Paint paint = new Paint();
            ColorMatrix cm = new ColorMatrix();
            cm.setSaturation(0);
            ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
            paint.setColorFilter(f);
            c.drawBitmap(source, 0, 0, paint);

            if(source!=null && source!=bmpGrayscale){
                source.recycle();
            }
            return bmpGrayscale;
        }

        @Override
        public String key() {
            return "gray";
        }
    }复制代码

2, 若是是多个Transformation操做,有2种方式应用
方式一:直接调用屡次transform 方法,不会覆盖的。它只是保存到了一个List 里面

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .centerCrop()
                .transform(new GrayTransformation())//度灰处理
                .transform(new BlurTransformation(this))//高斯模糊
                .into(mBlurImage);复制代码

须要注意调用的顺序
方式二:接受一个List,将Transformation 放大list 里

List<Transformation> transformations = new ArrayList<>();
        transformations.add(new GrayTransformation());
        transformations.add(new BlurTransformation(this));

        Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .centerCrop()
                .transform(transformations)
                .into(mBlurImage);复制代码

效果图:

gray_blur.png

如上图,第一张为度灰操做,第二张为 度灰+高斯模糊

另外发现了一个开源库,专门写了不少好玩的Transformation,有兴趣的能够看一下:
picasso-transformations

6. 请求优先级

Picasso 为请求设置有优先级,有三种优先级,LOW、NORMAL、HIGH。默认状况下都是NORMAL,除了调用fetch 方法,fetch 方法的优先级是LOW。

public enum Priority {
    LOW,
    NORMAL,
    HIGH
  }复制代码

能够经过priority方法设置请求的优先级,这会影响请求的执行顺序,可是这是不能保证的,它只会往高的优先级靠拢。代码以下:

Picasso.with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .priority(Picasso.Priority.HIGH)
               // .priority(Picasso.Priority.LOW)
                .into(mImageView);复制代码

7. Tag管理请求

Picasso 容许咱们为一个请求设置tag来管理请求,看一下对应的几个方法:
下面3个方法是Picasso这个类的:

  • cancelTag(Object tag) 取消设置了给定tag的全部请求
  • pauseTag(Object tag) 暂停设置了给定tag 的全部请求
  • resumeTag(Object tag) resume 被暂停的给定tag的全部请求

还有一个方法是RequestCreator的:

  • tag(Object tag) 为请求设置tag

几个方法的意思也很明确,就是咱们能够暂停、resume、和取消请求,能够用在哪些场景呢?

场景一: 好比一个照片流列表,当咱们快速滑动列表浏览照片的时候,后台会一直发起请求加载照片的,这可能会致使卡顿,那么咱们就能够为每一个请求设置一个相同的Tag,在快速滑动的时候,调用pauseTag暂停请求,当滑动中止的时候,调用resumeTag恢复请求,这样的体验是否是就会更好一些呢。

Adapter中添加以下代码:

Picasso.with(this).load(mData.get(position))
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .tag("PhotoTag")
                .into(holder.mImageView);复制代码

Activity中为RecyclerView添加滑动监听:

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                final Picasso picasso = Picasso.with(MainActivity.this);

                if (newState == SCROLL_STATE_IDLE) {
                    picasso.resumeTag("PhotoTag");
                } else {
                    picasso.pauseTag("PhotoTag");
                }
            }
        });复制代码

场景二: 好比一个照片流列表界面,在弱网环境下,加载很慢,退出这个界面时可能会有不少请求没有完成,这个时候咱们就可 以经过tag 来取消请求了。

@Override
    protected void onDestroy() {
        super.onDestroy();
        Picasso.with(this).cancelTag("PhotoTag");
    }复制代码

8. 同步/异步加载图片

Picasso 加载图片也有同步/异步两种方式
1,get() 同步
很简单,同步加载使用get() 方法,返回一个Bitmap 对象,代码以下:

try {
           Bitmap bitmap =  Picasso.with(this).load(URL).get();
        } catch (IOException e) {
            e.printStackTrace();
        }复制代码

注意:使用同步方式加载,不能放在主线程来作。

2,异步的方式加载图片,fetch()
通常直接加载图片经过into显示到ImageView 是异步的方式,除此以外,还提供了2个异步的方法:

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

    Picasso.with(this).load(URL).fetch(new Callback() {
              @Override
              public void onSuccess() {
                  //加载成功
              }
    
              @Override
              public void onError() {
                //加载失败
              }
          });复制代码

    这里就要吐槽一下接口设计了,回调并无返回Bitmap, 不知道做者是怎么考虑的,只是一个通知效果,知道请求失败仍是成功。
    fetch 方法异步加载图片并无返回Bitmap,这个方法在请求成功以后,将结果存到了缓存,包括磁盘和内存缓存。因此使用这种方式加载图片适用于这种场景:知道稍后会加载图片,使用fetch 先加载缓存,起到一个预加载的效果。

9. 缓存(Disk 和 Memory)

Picasso 有内存缓存(Memory)和磁盘缓存( Disk), 首先来看一下源码中对于缓存的介绍:

  • LRU memory cache of 15% the available application RAM
  • Disk cache of 2% storage space up to 50MB but no less than 5MB. (Note: this is only
    available on API 14+ or if you are using a standalone library that provides a disk cache on all API levels like OkHttp)
  • Three download threads for disk and network access.

能够看出,内存缓存是使用的LRU 策略的缓存实现,它的大小是内存大小的15%,能够自定义它的大小,最后在扩展那一章节再讲,磁盘缓存是磁盘容量的2%可是不超过50M,很多于5M。处理一个请求的时候,按照这个顺讯检查:memory->disk->network 。先检查有木有内存缓存,若是命中,直接返回结果,不然检查磁盘缓存,命中则返回结果,没有命中则从网上获取。

默认状况下,Picasso 内存缓存和磁盘缓存都开启了的,也就是加载图片的时候,内存和磁盘都缓存了,可是有些时候,咱们并不须要缓存,好比说:加载一张大图片的时候,若是再内存中保存一份,很容易形成OOM,这时候咱们只但愿有磁盘缓存,而不但愿缓存到内存,所以就须要咱们设置缓存策略了。Picasso 提供了这样的方法。

1,memoryPolicy 设置内存缓存策略
就像上面所说的,有时候咱们不但愿有内存缓存,咱们能够经过 memoryPolicy 来设置。MemoryPolicy是一个枚举,有两个值

NO_CACHE:表示处理请求的时候跳过检查内存缓存
NO_STORE: 表示请求成功以后,不将最终的结果存到内存。

示例代码以下:

with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE) //静止内存缓存
                .into(mBlurImage);复制代码

2,networkPolicy 设置磁盘缓存策略
和内存缓存同样,加载一张图片的时候,你也能够跳过磁盘缓存,和内存缓存策略的控制方式同样,磁盘缓存调用方法networkPolicy(NetworkPolicy policy, NetworkPolicy... additional) , NetworkPolicy是一个枚举类型,有三个值:

NO_CACHE: 表示处理请求的时候跳过处理磁盘缓存
NO_STORE: 表示请求成功后,不将结果缓存到Disk,可是这个只对OkHttp有效。
OFFLINE: 这个就跟 上面两个不同了,若是networkPolicy方法用的是这个参数,那么Picasso会强制此次请求从缓存中获取结果,不会发起网络请求,无论缓存中可否获取到结果。

使用示例:

with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)//跳过内存缓存
                .networkPolicy(NetworkPolicy.NO_CACHE)//跳过磁盘缓存
                .into(mBlurImage);复制代码

强制从缓存获取:

with(this).load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .networkPolicy(NetworkPolicy.OFFLINE)//强制从缓存获取结果
                .into(mBlurImage);复制代码

10. Debug 和日志

1,缓存指示器

上一节说了,Picasso 有内存缓存和磁盘缓存,先从内存获取,没有再去磁盘缓存获取,都有就从网络加载,网络加载是比较昂贵和耗时的。所以,做为一个开发者,咱们每每须要加载的图片是从哪儿来的(内存、Disk仍是网络),Picasso让咱们很容易就实现了。只须要调用一个方法setIndicatorsEnabled(boolean)就能够了,它会在图片的左上角出现一个带色块的三角形标示,有3种颜色,绿色表示从内存加载、蓝色表示从磁盘加载、红色表示从网络加载。

Picasso.with(this)
        .setIndicatorsEnabled(true);//显示指示器复制代码

效果图:

cache_indicator.png

如上图所示,第一张图从网络获取,第二张从磁盘获取,第三张图从内存获取。

看一下源码中定义指示器的颜色:

/** Describes where the image was loaded from. */
  public enum LoadedFrom {
    MEMORY(Color.GREEN),
    DISK(Color.BLUE),
    NETWORK(Color.RED);

    final int debugColor;

    private LoadedFrom(int debugColor) {
      this.debugColor = debugColor;
    }
  }复制代码

能够很清楚看出,对应三种颜色表明着图片的来源。

2,日志
上面的指示器可以很好的帮助咱们看出图片的来源,可是有时候咱们须要更详细的信息,Picasso,能够打印一些日志,好比一些关键方法的执行时间等等,咱们只须要调用setLoggingEnabled(true)方法,而后App在加载图片的过程当中,咱们就能够从logcat 看到一些关键的日志信息。

Picasso.with(this)
          .setLoggingEnabled(true);//开启日志打印复制代码

11. Picasso 扩展

到目前为止,Picasso的基本使用已经讲得差很少了,可是在实际项目中咱们这可能还知足不了咱们的需求,咱们须要对它作一些本身的扩展,好比咱们须要换缓存的位置、咱们须要扩大缓存、自定义线程池、自定义下载器等等。这些都是能够的,接下来咱们来看一下能够作哪些方面的扩展。

1,用Builder 本身构造一个Picasso Instance
咱们来回顾一下前面是怎么用Picasso 加载图片的:

Picasso.with(this)
       .load("http://ww3.sinaimg.cn/large/610dc034jw1fasakfvqe1j20u00mhgn2.jpg")
       .into(mImageView);复制代码

总共3步:
1,用with方法获取一个Picasso 示例
2,用load方法加载图片
3,用into 放法显示图片

首先Picasso是一个单例模式,咱们每一次获取的示例都是默认提供给咱们的实例。可是也能够不用它给的Instance,咱们直接用builder来构造一个Picasso:

Picasso.Builder builder = new Picasso.Builder(this);
        //构造一个Picasso
        Picasso picasso = builder.build();
        //加载图片
        picasso.load(URL)
                .into(mImageView);复制代码

这样咱们就构造了一个局部的Picasso实例,固然了,咱们直接用new 了一个builder,而后build()生成了一个Picasso。这跟默认的经过with方法获取的实例是同样的。那么如今咱们就能够配置一些自定义的功能了。
2, 配置自定义下载器 downLoader
若是咱们不想用默认提供的Downloader,那么咱们能够自定义一个下载器而后配置进去。举个例子:

(1) 先自定义一个Downloader(只是举个例子,并无实现):

/** * Created by zhouwei on 17/2/26. */

public class CustomDownloader implements Downloader {

    @Override
    public Response load(Uri uri, int networkPolicy) throws IOException {
        return null;
    }

    @Override
    public void shutdown() {

    }
}复制代码

(2) 而后经过builder 配置:

//配置下载器
        builder.downloader(new CustomDownloader());
        //构造一个Picasso
        Picasso picasso = builder.build();复制代码

这样配置后,咱们用build()生成的Picasso 实例来加载图片就会使用自定义的下载器来下载图片了。

3, 配置缓存
前面说过,内存缓存是用的LRU Cahce ,大小是手机内存的15% ,若是你想缓存大小更大一点或者更小一点,能够自定义,而后配置。

//配置缓存
        LruCache cache = new LruCache(5*1024*1024);// 设置缓存大小
        builder.memoryCache(cache);复制代码

上面只是一个简单的举例,固然了你能够自定义,也可使用LRUCache,改变大小,改变存储路径等等。

提示: 很遗憾,好像没有提供改变磁盘缓存的接口,那就只能用默认的了。

4, 配置线程池
Picasso 默认的线程池的核心线程数为3,若是你以为不够用的话,能够配置本身须要的线程池,举个列子:

//配置线程池
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        builder.executor(executorService);复制代码

5, 配置全局的 Picasso Instance
上面说的这些自定义配置项目都是应用在一个局部的Picasso instance 上的,咱们不可能每一次使用都要从新配置一下,这样就太麻烦了。咱们但愿咱们的这些自定义配置能在整个项目都应用上,而且只配置一次。其实Picasso 给咱们提供了这样的方法。能够调用setSingletonInstance(Picasso picasso)就能够了,看一下这个方法的源码:

/** * Set the global instance returned from {@link #with}. * <p> * This method must be called before any calls to {@link #with} and may only be called once. */
  public static void setSingletonInstance(Picasso picasso) {
    synchronized (Picasso.class) {
      if (singleton != null) {
        throw new IllegalStateException("Singleton instance already exists.");
      }
      singleton = picasso;
    }
  }复制代码

设置一个经过with方法返回的全局instance。咱们只但愿配置一次,因此,咱们应该在Application 的onCreate方法中作全局配置就能够了。app一启动就配置好,而后直接和前面的使用方法同样,调用with方法获取Picasso instance 加载图片就OK了。

所以在Application 中添加以下代码:

@Override
    public void onCreate() {
        super.onCreate();

        // 配置全局的Picasso instance 

        Picasso.Builder builder = new Picasso.Builder(this);
        //配置下载器
        builder.downloader(new CustomDownloader());
        //配置缓存
        LruCache cache = new LruCache(5*1024*1024);// 设置缓存大小
        builder.memoryCache(cache);
        //配置线程池
        ExecutorService executorService = Executors.newFixedThreadPool(8);
        builder.executor(executorService);

        //构造一个Picasso
        Picasso picasso = builder.build();
        // 设置全局单列instance 
        Picasso.setSingletonInstance(picasso);


    }复制代码

而后应用这些自定义配置加载图片

Picasso.with(this).load("http://ww3.sinaimg.cn/large/610dc034jw1fasakfvqe1j20u00mhgn2.jpg").into(mImageView);复制代码

用法和之前的同样,可是咱们已经将咱们的自定义配置应用上了。

结尾

以上就是对Picasso 用法的所有总结,若有什么问题,欢迎留言指正。Picasso真的是一个强大的图片加载缓存库,API 简单好用,并且是链式调用的(这点我特别喜欢)。官方文档写的比较简单,不少用法都要看源码和注释才知道。但愿本文能给才开始使用Picasso 的同窗一点帮助。

参考

Picasso官网
Picasso — Getting Started

相关文章
相关标签/搜索