Android图片加载框架Picasso最全使用教程 四

  通过前几篇的学习,我们已经对Picasso的加载图片的用法有了很深的了解,接下来我们开始分析Picasso为我们提供的其他高级功能及内存分析,Let’s Go !

Picasso进行图片的旋转(Rotation)

简单的旋转,只需要增加一个角度即可,调用rotate(float degrees)

当我们对一张图片需要进行简单的旋转处理时,只需要调用传入旋转的角度,大于0小于360即可,上代码:

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .rotate(90f) //旋转90.into(imageViewSimpleRotate);

根据某个点进行复杂的旋转操作

因为图片的旋转都是相对(0,0)进行操作,所以如果我们想自定义相对于某个点,也是可以的,只需要调用
.rotate(float degrees, float pivotX, float pivotY)

Picasso
    .with(context)
    .load(R.drawable.floorplan)
    .rotate(45f, 200f, 100f)
    .into(imageViewComplexRotate);

对图片的转化(Transformation)

模糊一张图片

我们可以在一张图片进行展示之前,对其进行操作,然后在展示;这时我们需要定义一个类实现Transformation,然后重写里面重要的方法,直接上代码:

public class BlurTransformation implements Transformation {

    RenderScript rs;

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

    @Override
    public Bitmap transform(Bitmap bitmap) {
        // 创建一个Bitmap作为最后处理的效果Bitmap
        Bitmap blurredBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

        // 分配内存
        Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);
        Allocation output = Allocation.createTyped(rs, input.getType());

        // 根据我们想使用的配置加载一个实例
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        script.setInput(input);

        // 设置模糊半径
        script.setRadius(10);

        //开始操作
        script.forEach(output);

        // 将结果copy到blurredBitmap中
        output.copyTo(blurredBitmap);

        //释放资源
        bitmap.recycle();

        return blurredBitmap;
    }

    @Override
    public String key() {
        return "blur";
    }
}

//然后调用即可

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .transform(new BlurTransformation(context))
    .into(imageViewTransformationBlur);

在图片被加载之前就会被我们先处理一遍;

对加载的资源进行复杂的操作(模糊+缩放)

我们应该注意到,Picasso给我们提供了一个这样的API,允许我们将参数设置为一个Transformations的集合
transform(List transformations),这就意味着我们可以对资源进行一系列的操作;上代码:

public class GrayscaleTransformation implements Transformation {

    private final Picasso picasso;

    public GrayscaleTransformation(Picasso picasso) {
        this.picasso = picasso;
    }

    @Override
    public Bitmap transform(Bitmap source) {
        Bitmap result = createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
        Bitmap noise;
        try {
            noise = picasso.load(R.drawable.noise).get();
        } catch (IOException e) {
            throw new RuntimeException("Failed to apply transformation! Missing resource.");
        }

        BitmapShader shader = new BitmapShader(noise, REPEAT, REPEAT);

        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.setSaturation(0);
        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);

        Paint paint = new Paint(ANTI_ALIAS_FLAG);
        paint.setColorFilter(filter);

        Canvas canvas = new Canvas(result);
        canvas.drawBitmap(source, 0, 0, paint);

        paint.setColorFilter(null);
        paint.setShader(shader);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

        source.recycle();
        noise.recycle();

        return result;
    }

    @Override
    public String key() {
        return "grayscaleTransformation()";
    }
}

//下面进行调用

List transformations = new ArrayList<>();

transformations.add(new GrayscaleTransformation(Picasso.with(context)));
transformations.add(new BlurTransformation(context));

Picasso
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[0])
    .transform(transformations)
    .into(imageViewTransformationsMultiple);

这个transformations我相信已经能够给你足够强大的功能供你处理图片资源,到这里,Picasso基本所有的高级功能都被你所掌握了,已经非常好了,下面我们就开始分析Picasso的缓存组件,让我们继续揭开Picasso的神秘面纱;

关于缓存机制

Picasso默认的缓存分配大小特点:

  • LRU缓存占应用程序可用内存的15%
  • 本地缓存占到硬盘空间的2%但不超过50M并且不小于5M(前提是这种情况只在4.0以上有效果,或者你能像OKHttp那样提供一个本地缓存库来支持全平台)
  • Picasso默认开启3个线程来进行本地与网络之间的访问
  • Picasso加载图片顺序, 内存–>本地–>网络

Memory Policy

可能有的时候你不想让Picasso去内存中进行读取而跳过此步骤,这时你可以在进行网络请求时调用memoryPolicy(MemoryPolicy policy, MemoryPolicy... additional),MemoryPolicy是一个枚举,只有两个值 NO_CACHE 和 ‘NO_STORE`

  • NO_CACHE - 让Picasso跳过从内存中读取图片这一操作

  • NO_STORE - 如果你的图片只加载一次就没用了,就调用该值,这样的话Picasso就不会在内存及本地进行缓存了

代码示例:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[1])
    .memoryPolicy(MemoryPolicy.NO_CACHE)
    .into(imageViewFromDisk);

当然,你也可以这样调用:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[1])
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .into(imageViewFromDisk);

注意:调用.memoryPolicy(MemoryPolicy.NO_CACHE)虽然能避免Picasso从内存中读取资源,但是并不能避免从本地读取资源,如果你也想跳过从本地读取这一过程,请看NetworkPolicy.

NetworkPolicy

就像MemoryPolicy负责管理内存缓存一样,NetworkPolicy就是负责管理本地缓存的,而且二者的用法一模一样,NetworkPolicy也是一个枚举,不过它有三个值:

  • NO_CACHE - 让Picasso跳过从本地读取资源这一过程
  • NO_STORE - 让Picasso不进行本地图片缓存
  • OFFLINE - 让Picasso加载图片的时候只从本地读取除非联网正常并且本地找不到资源的情况下

示例代码:

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork);

当然,你也可以配合MemoryPolicy一起使用

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork); 

查看图片都来源于何处,缓存指示器

作为一个有经验的猿猿,我们肯定想知道我们所加载的图片来源于何处,是内存,本地还是从网络加载的,当然这个动作Picasso已经为我们想好了,我们只需要在请求的时候调用.setIndicatorsEnabled(true);就行了,代码:

Picasso  
    .with(context)
    .setIndicatorsEnabled(true);

这样每张图片在显示的时候,左上角都会有一个小标记,分别又三种三色,蓝色,绿色,红色;

  • 蓝色 - 从内存中获取,是最佳性能展示
  • 绿色 - 从本地获取,性能一般
  • 红色 - 从网络加载,性能最差

Android图片加载框架Picasso最全使用教程 四_第1张图片

查看图片加载用时

缓存指示器能帮助我们查看图片的加载来源,但是并不能精确的知道每张图片从网络加载时所用的时间,在请求开始我们就加上调用.setLoggingEnabled(true),来通过输出日志的方式查看每张网络请求的资源所用的时间; 上代码:

Picasso  
    .with(context)
    .setLoggingEnabled(true);

Picasso  
    .with(context)
    .load(UsageExampleListViewAdapter.eatFoodyImages[2])
    .memoryPolicy(MemoryPolicy.NO_CACHE)
    .networkPolicy(NetworkPolicy.NO_CACHE)
    .into(imageViewFromNetwork);

然后通过在控制台上查看日志信息,如下:

D/Picasso﹕ Main        created      [R0] Request{http://i.imgur.com/rT5vXE1.jpg}  
D/Picasso﹕ Dispatcher  enqueued     [R0]+21ms  
D/Picasso﹕ Hunter      executing    [R0]+26ms  
D/Picasso﹕ Hunter      decoded      [R0]+575ms  
D/Picasso﹕ Dispatcher  batched      [R0]+576ms for completion  
D/Picasso﹕ Main        completed    [R0]+807ms from NETWORK  
D/Picasso﹕ Dispatcher  delivered    [R0]+809ms  

整体加载分析StatsSnapshot

你可能有一个场景,需要看一个大图的加载在内存中占用了多大,你可以调用StatsSnapshot即可,代码:


StatsSnapshot picassoStats = Picasso.with(context).getSnapshot();  
//然后打印
Log.d("Picasso Stats", picassoStats.toString()); 

最后输出结果为:


D/Picasso Stats﹕ StatsSnapshot{
maxSize=28760941, 
size=26567204, 
cacheHits=30, 
cacheMisses=58, 
downloadCount=0, 
totalDownloadSize=0, 
averageDownloadSize=0, 
totalOriginalBitmapSize=118399432, 
totalTransformedBitmapSize=96928004, 
averageOriginalBitmapSize=2466654, 
averageTransformedBitmapSize=2019333, 
originalBitmapCount=48, 
transformedBitmapCount=41, 
timeStamp=1432576918067}

OK,到此关于Picasso的高级用法我们都有了一定得了解,后面我们将介绍Picasso.Builder来改变Picasso的实例,愿大家都有一个美好的一天.

你可能感兴趣的:(Android图片加载,Android开源框架解析)