第三方开源库--> Picasso

Posted Kevin-Dev

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三方开源库--> Picasso相关的知识,希望对你有一定的参考价值。

不断学习,做更好的自己!💪

视频号CSDN简书
欢迎打开微信,关注我的视频号:KevinDev点我点我

写在前面

android 中有几个比较有名的图片加载框架,Universal ImageLoader、Picasso、Glide 和 Fresco。Picasso 是 Square 公司开源的 Android 端的图片加载和缓存框架。Square 真是一家良心公司啊,为我们 Android 开发者贡献了很多优秀的开源项目有木有!像什么 Rerefoit 、OkHttp、LeakCanary、Picasso 等等都是非常火的开源项目。

实战

1. 在 app/build.gradle 中添加依赖:

    // picasso
    implementation 'com.squareup.picasso:picasso:2.71828'

2. 加载显示图片
将 Picasso 添加到项目之后,我们就可以用它来加载图片了,使用方法非常简单:

Picasso.get()
       .load("http://ww3.sinaimg.cn/large/610dc034jw1fasakfvqe1j20u00mhgn2.jpg")
       .into(mImageView);

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

  • 加载一个以 Uri 路径给的图片
Uri uri = Uri.parse(ANDROID_RESOURCE + context.getPackageName() + FOREWARD_SLASH + resourceId);

Picasso.get().load(uri).into(mImageView);
  • 加载 File 中的图片
Picasso.get().load(file).into(mImageView);
  • 加载本地资源图片
Picasso.get().load(R.mipmap.ic_launcher).into(mImageView);

3. 占位图
我们的项目中通常最常用的就是加载网络图片,但是由于网络环境的差异,有时侯加载网络图片的过程有点慢,这样界面上就会显示空ImageView什么也看不见,用户体验非常不好。

  • placeholder
    提供一张在网络请求还没有完成时显示的图片,它必须是本地图片,代码如下:
Picasso.get()
	   .load(URL)
       .placeholder(R.drawable.default_bg)
       .into(mImageView);
  • error
    提供一张在加载图片出错的情况下显示的默认图:
Picasso.get()
	   .load(URL)
       .placeholder(R.drawable.default_bg)
       .error(R.drawable.error_iamge)
       .into(mImageView);
  • noPlaceholder
    在调用 into 的时候明确告诉你没有占位图设置。注意: placeholder 和 noPlaceholder 不能同时应用在同一个请求上,会抛异常。
Picasso.get()
	   .load(URL)
       .noPlaceholder()
       .error(R.drawable.error_iamge)
       .into(mImageView);
  • noFade
    无论你是否设置了占位图,Picasso 从磁盘或者网络加载图片时,into 显示到 ImageView 都会有一个简单的渐入过度效果,让你的 UI 视觉效果更柔顺丝滑一点,如果你不要这个渐入的效果(没有这么坑爹的需求吧!!!),就调用 noFade 方法。
Picasso.get()
	   .load(URL)
       .placeholder(R.drawable.default_bg)
       .error(R.drawable.error_iamge)
       .noFade()
       .into(mImageView);

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

  • Resize(int w,int h)
    在项目中,为了带宽、内存使用和下载速度等考虑,服务端给我们的图片的 size 应该和我们 View 实际的 size 一样的,但是实际情况并非如此,服务端可能给我们一些奇怪的尺寸的图片,我们可以使用 resize(int w,int hei) 来重新设置尺寸。
Picasso.get().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.get().load(URL)
             .placeholder(R.drawable.default_bg)
             .error(R.drawable.error_iamge)
             .resize(R.dimen.image_width,R.dimen.image_height)
             .into(mImageView);
  • onlyScaleDown
    当调用了 resize 方法重新设置图片尺寸的时候,调用 onlyScaleDown 方法,只有当原始图片的尺寸大于我们指定的尺寸时,resize 才起作用如:
Picasso.get().load(URL)
             .placeholder(R.drawable.default_bg)
             .error(R.drawable.error_iamge)
             .resize(4000,2000)
             .onlyScaleDown()
             .into(mImageView);

只有当原来的图片尺寸大于 4000 x 2000 的时候,resize 才起作用。

  • 图片裁剪 centerCrop()
    Picasso 给我们提供了一个方法,centerCrop,充满 ImageView 的边界,居中裁剪。
Picasso.get().load(URL)
             .placeholder(R.drawable.default_bg)
             .error(R.drawable.error_iamge)
             .resize(400,200)
             .centerCrop()
             .into(mImageView);
  • centerInside
    上面的 centerCrop 是可能看不到全部图片的,如果你想让 View 将图片展示完全,可以用 centerInside ,但是如果图片尺寸小于 View 尺寸的话,是不能充满 View 边界的。
Picasso.get().load(URL)
             .placeholder(R.drawable.default_bg)
             .error(R.drawable.error_iamge)
             .resize(400,200)
             .centerInside()
             .into(mImageView);
  • fit
    它会自动测量我们的 View 的大小,然后内部调用 reszie 方法把图片裁剪到 View 的大小,这就帮我们做了计算 size 和调用 resize 这2步。最好配合前面的 centerCrop 使用。代码如下:
Picasso.get().load(URL)
             .placeholder(R.drawable.default_bg)
             .error(R.drawable.error_iamge)
             .fit()
             .centerCrop()
             .into(mImageView);

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

  • 图片旋转 Rotation()
    在图片显示到 ImageView 之前,还可以对图片做一些旋转操作,调用 rotate(int degree) 方法:
Picasso.get()
	   .load(URL)
       .placeholder(R.drawable.default_bg)
       .error(R.drawable.error_iamge)
       .rotate(180)
       .into(mImageView);

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

Picasso.get()
	   .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 来完成。
a) 首先定义一个转换器继承 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";
        
    

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

Picasso.get().load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .transform(new BlurTransformation(this))
                .into(mBlurImage);

需求:我想先做个度灰处理然后在做一个高斯模糊图。
a. 度灰的 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";
        
    

如果是多个Transformation操作,有 2 种方式应用。
方式一:直接调用多次 transform 方法,不会覆盖的。

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

        Picasso.get().load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .centerCrop()
                .transform(transformations)
                .into(mBlurImage);

方式二:接受一个 List,将 Transformation 放大 list 里

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

        Picasso.get().load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .fit()
                .centerCrop()
                .transform(transformations)
                .into(mBlurImage);

另外发现了一个开源库,专门写了很多好玩的Transformation,有兴趣的可以看一下:
picasso-transformations

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

public enum Priority 
    LOW,
    NORMAL,
    HIGH
  

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

 Picasso.get().load(URL)
                .placeholder(R.drawable.default_bg)
                .error(R.drawable.error_iamge)
                .priority(Picasso.Priority.HIGH)
               // .priority(Picasso.Priority.LOW)
                .into(mImageView);

7. 同步/异步加载图片
1,同步加载图片
很简单,同步加载使用get() 方法,返回一个Bitmap 对象,代码如下:

try 
           Bitmap bitmap =  Picasso.with(this).load(URL).get();
         catch (IOException e) 
            e.printStackTrace();
        

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

2,异步加载图片
一般直接加载图片通过 into 显示到 ImageView 是异步的方式,除此之外,还提供了 2 个异步的方法:

Picasso.get().load(URL).fetch(new Callback() 
            @Override
            public void onSuccess() 
                //加载成功
            

            @Override
            public void onError() 
              //加载失败
            
        );

参考
Picasso官网
Picasso — Getting Started

以上是关于第三方开源库--> Picasso的主要内容,如果未能解决你的问题,请参考以下文章

Android图片加载库:最全面的Picasso讲解

Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等

Picasso,Glide,Fresco那个好?

图片加载框架之Glide和Picasso

Android开源框架——Picasso

Android BitmapFactory.Options 解决大图片加载OOM问题