开源框架之[-Picasso-]应用篇

作者: e4e52c116681 | 来源:发表于2019-02-11 22:11 被阅读23次

零、前言

Picasso是一个图片加载的框架,内部依赖了OkHttp,OkHttp内部依赖了okio
依赖:implementation 'com.squareup.picasso:picasso:2.71828'
本篇讲一下Picasso的用法,下一篇分析一下Picasso的源码

picasso.png

一、Picasso的缓存相关

 Picasso.get().setIndicatorsEnabled(true);
 |--标记处图片加载的位置
    |--红色,网络加载
    |--绿色,内存加载
    |--蓝色,磁盘加载 

1.点击时进行网络加载

可见是红色,网络加载

String url = "http://192.168.43.60:8080/imgs/HXqqASHJETSlvpnc.jpg";
imageView.setOnClickListener(v -> {
    Picasso.get().load(url)
            .into(imageView);
});
网络加载.png
2.再次点击加载网络图片

可见是绿色,内存加载。这时并未去请求网络加载图片,直接用内存中的缓存图片

内存加载.png
3.退出再进来加载网络图片

可见是蓝色,即从磁盘读取的本地文件

磁盘加载.png

从缓存来看标准的DiskLruCache

|---文件名:键的md5值
|---XXXXX.0 文件:请求信息
|---XXXXX.1 文件:响应数据(这里即是图片)
|---journal 文件:使用日志
|---文件大小: 从服务器端的资源来看,并未压缩
缓存.png 服务器端.png
5.小结一下:

内存缓存-->本地磁盘缓存-->网络缓存(即资源)

三级缓存.png

二、缓存策略

1.做个试验

貌似完美无缺,但是...图片的更新是个问题
现在将服务端的图片更新一下:发现现在客户端是无法更新的
也就是缓存会妨碍获取更新后的图片,必须清除缓存才能更新,所以凡事有利必有弊

更新图片.png 客户端更新图片.png
2.网络策略:NetworkPolicy与内存策略MemoryPolicy

比如下拉刷新的时候可以直接越过内存和磁盘,请求网络
因为User的动作的目的性明确,普通情况可以使用缓存,你也可以视情况自己定制

定制缓存策略.png
public enum NetworkPolicy {
NO_CACHE(1 << 0),//跳过检查磁盘缓存,强制通过网络加载
NO_STORE(1 << 1),//不将结果存储到磁盘缓存
OFFLINE(1 << 2);//强制使用磁盘缓存,跳过网络

public enum MemoryPolicy {
NO_CACHE(1 << 0),//处理请求时跳过内存缓存查找
NO_STORE(1 << 1);//不将最终结果存储到内存缓存中。
  用于一次性请求,以避免从缓存中删除其他图片缓存。

单击三级缓存,长按请求网络

String url = "http://192.168.43.60:8080/imgs/HXqqASHJETSlvpnc.jpg";
imageView.setOnClickListener(v -> {
    Picasso.get()
            .load(url)
            .into(imageView);
});

imageView.setOnLongClickListener(v -> {
    Picasso.get()
            .load(url)
            .networkPolicy(NetworkPolicy.NO_CACHE)//跳过磁盘缓存
            .memoryPolicy(MemoryPolicy.NO_CACHE) //跳过内存缓存
            .into(imageView);
    return true;
});

三、Picasso的图片变换
ImageView:300dp*300dp
资源图片:3600px*2400px
测试图.png
1.对比一下点击前后的变化

这个是使用Picasso

点击前后.png

直接BitmapFactory.decodeFile

BitmapFactory.decodeFile.png

可见基本上差不多,说明Picasso在加载大图是,默认情况下并未优化


2.resize方法和resizeDimen

resize方法可以对大图进行优化,但本地缓存的大小依然是原图大小
两者本质上一样resizeDimen是使用dimens的尺寸资源,可以dp

resize.png 重置尺寸.png
3.fit和centerCrop

注意centerCrop有个一参的入参:Gravity.XXX来控制裁剪的位置(默认中心裁剪)
centerCrop必须调用resize才行,fit调用后,deferred = true; 在into方法中会触发resize
另外fit不能和resize共存

java.lang.IllegalStateException: Center crop requires calling resize with positive width and height.
fit.png
4..transform

总得来说,就是针对Bitmap做一些操作,可参见Bitmap专题,再把新的Bitmap返回出去
下面给出三个简单的操作,灰度,模糊,路径裁剪

变化.png
---->[灰度操作]------------
public class GrayTransformation implements Transformation {
    @Override
    public Bitmap transform(Bitmap source) {
        Bitmap bmpGrayScale = Bitmap.createBitmap(
                source.getWidth(), source.getHeight(), Bitmap.Config.RGB_565);
        Canvas c = new Canvas(bmpGrayScale);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        paint.setColorFilter(new ColorMatrixColorFilter(cm));
        c.drawBitmap(source, 0, 0, paint);
        if (source != bmpGrayScale) {
            source.recycle();
        }
        return bmpGrayScale;
    }
    @Override
    public String key() {
        return "BlurTransformation";
    }
}

---->[模糊操作]------------
public class BlurTransformation implements Transformation {
    private Context mContext;
    private int mRadius;

    public BlurTransformation(Context context, int radius) {
        mContext = context;
        mRadius = radius;
    }

    @Override
    public Bitmap transform(Bitmap source) {
        RenderScript rs = RenderScript.create(mContext);
        Bitmap blurredBitmap = source.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(mRadius);
        script.forEach(output);
        output.copyTo(blurredBitmap);
        source.recycle();
        return blurredBitmap;
    }

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

---->[星星裁剪类]------------
/**
 * 作者:张风捷特烈<br/>
 * 时间:2018/8/30 0030:21:44<br/>
 * 邮箱:1981462002@qq.com<br/>
 * 说明:星星裁剪类
 */
public class StarTransformation implements Transformation {
    private int num;
    private boolean mOutline;
    public StarTransformation(int num,boolean outline) {
        this.num = num;
        mOutline = outline;
    }
    @Override
    public Bitmap transform(Bitmap source) {
        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
        if (squaredBitmap != source) {
            source.recycle();
        }
        int strokeWidth = (int) (size / 120f);
        Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
        Canvas canvas = new Canvas(bitmap);
        Paint avatarPaint = new Paint();
        BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAM
        avatarPaint.setShader(shader);
        Paint outlinePaint = new Paint();
        outlinePaint.setColor(Color.WHITE);
        outlinePaint.setStyle(Paint.Style.STROKE);
        outlinePaint.setStrokeWidth(strokeWidth);
        outlinePaint.setAntiAlias(true);
        Path starPath = nStarPath(num, size / 2, size / 2 * 0.8f);
        canvas.drawPath(starPath, avatarPaint);
        if (mOutline) {
            canvas.drawPath(starPath, outlinePaint);
        }
        squaredBitmap.recycle();
        return bitmap;
    }
    private Path nStarPath(int num, float R, float r) {
        Path path = new Path();
        float perDeg = 360 / num;
        float degA = perDeg / 2 / 2;
        float degB = 360 / (num - 1) / 2 - degA / 2 + degA;
        float dx = R * cos(degA);
        float dy = R;
        path.moveTo(cos(degA) * R + dx, -sin(degA) * R + dy);
        for (int i = 0; i <= num; i++) {
            path.lineTo(cos(degA + perDeg * i) * R + dx, -sin(degA + perDeg * i) * R + dy);
            path.lineTo(cos(degB + perDeg * i) * r + dx, -sin(degB + perDeg * i) * r + dy);
        }
        path.close();
        return path;
    }
    private float sin(float deg) {
        return (float) Math.sin(deg / 180 * Math.PI);
    }
    private float cos(float deg) {
        return (float) Math.cos(deg / 180 * Math.PI);
    }
    @Override
    public String key() {
        return "StarTransformation";
    }
}

四、常规使用

1.其他设置
旋转.png
.placeholder(R.mipmap.icon_default)//默认占位图
.error(R.mipmap.error)//错误显示图
.rotate(90)//旋转90度
.noFade()//取消渐变---默认有渐变

2.加载的形式

说是四种,核心都差不多,就是找资源而已

四种加载方式.png
String url = "http://192.168.10.104:8080/imgs/HXqqASHJETSlvpnc.jpg";
File file = new File(getCacheDir(), "/picasso-cache/200ca0eb49c069b127236c34582a5c10.1");
Uri uri = Uri.parse("file:///android_asset/wy.jpg");
Picasso.get()
//          .load(url)//加载url
//          .load(R.mipmap.icon_default)//加载资源文件
//          .load(file)//加载文件
        .load(uri)//assets文件---Uri形式

3.自己可以完成一下下面的效果

Picasso的基本用法也就这么多,明天进源码里去看看


后记:捷文规范

1.本文成长记录及勘误表
项目源码 日期 附录
V0.1-- 2018-2-11

发布名:开源框架之[-Picasso-]应用篇
捷文链接:https://www.jianshu.com/p/075f846207a9

2.更多关于我
笔名 QQ 微信
张风捷特烈 1981462002 zdl1994328

我的github:https://github.com/toly1994328
我的简书:https://www.jianshu.com/u/e4e52c116681
我的掘金:https://juejin.im/user/5b42c0656fb9a04fe727eb37
个人网站:http://www.toly1994.com

3.声明

1----本文由张风捷特烈原创,转载请注明
2----欢迎广大编程爱好者共同交流
3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
4----看到这里,我在此感谢你的喜欢与支持

icon_wx_200.png

相关文章

网友评论

    本文标题:开源框架之[-Picasso-]应用篇

    本文链接:https://www.haomeiwen.com/subject/gfpceqtx.html