图片处理篇--Picasso

本篇就来讲一讲Android的图片的处理,在Android App上加载图片是很常见的,同时也是很容易造成OOM。

如果你对加载大图、图片缓存、OOM异常等问题不太了解,请先看看郭大神这篇文章

Android高效加载大图、多图解决方案,有效避免程序OOM,分析的很详细;


当然,本篇主要是让你学会使用Picasso和Fresco这两个图片处理库,这两个库的使用方法在网上都很多,而且都非常简单,但是今天我会说点不一样的!


Picasso2 && OkHttp3

我在 第六篇 网络请求篇(上) 的时候为了说OkHttp3,就示例使用OkHttp3加载图片,其实那不是很好的加载图片的方法,Square有一款专门的图片加载工具Picasso:官网地址

Picasso的常规使用

在官网上可以看到,Picasso的使用方法很简单:

 Picasso.with(context).load("path").into(imageView);

通过官网上面的解析,我们还可以了解到Picasso的其它的一些用法,比如:placeholder()、resize()、centerCrop()、error()等等;都可以很简单的实现。

同时,Picasso的内部会默认帮你实现了内存缓存,其大小为内存1/7左右,所以不做详述。因为今天我们要说的是本地缓存,如何用OkHttp3配合Picasso实现本地缓存呢?


Picasso的本地缓存

由于Picasso和OkHttp同属Square公司,所以,他们互相支持调用;
我在写这篇博客之前在google了很久,stackOverflow上面的用OkHttp写缓存都比较简单,也没有比较权威的说法。于是在github上面找到了Jake Wharton大神写的关于Picasso使用OkHttp3的配置,瞬间觉得这就是权威!看源码

这里不把全部代码贴出来,部分解析:大家需要明确一点Downloader已经实现了DiskLruCache,我们现在需要的是配合OkHttp的网络请求来重写缓存。

public final class OkHttp3Downloader implements Downloader {
    private static final String PICASSO_CACHE = "picasso-cache";
    private static final int MIN_DISK_CACHE_SIZE = 5 * 1024 * 1024; // 5MB
    private static final int MAX_DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB

    //新建一个默认的缓存文件夹
    //可以在你手机中/android/data/yourapp/picasso-cache文件夹中可以找到
    private static File createDefaultCacheDir(Context context) {
        File cache = new         
        File(context.getApplicationContext().getCacheDir(), PICASSO_CACHE);
        if (!cache.exists()) {
            //noinspection ResultOfMethodCallIgnored
            cache.mkdirs();
        }
        return cache;
    }

    //计算缓存文件的大小,
    private static long calculateDiskCacheSize(File dir) {
        long size = MIN_DISK_CACHE_SIZE;
        try {
            StatFs statFs = new StatFs(dir.getAbsolutePath());
            long available = ((long) statFs.getBlockCount()) * statFs.getBlockSize();
          // Target 2% of the total space.
          size = available / 50;
          } catch (IllegalArgumentException ignored) {}

          // Bound inside min/max size for disk cache.
        return Math.max(Math.min(size, MAX_DISK_CACHE_SIZE), MIN_DISK_CACHE_SIZE);

    }

    ......

    //网络请求时的本地缓存处理,如何没有网络且有缓存,则从缓存中读取;
    @Override public Response load(Uri uri, int networkPolicy) throws IOException {
        CacheControl cacheControl = null;
        if (networkPolicy != 0) {
            if (NetworkPolicy.isOfflineOnly(networkPolicy)) {
                cacheControl = CacheControl.FORCE_CACHE;
            } else {
                CacheControl.Builder builder = new CacheControl.Builder();
                if (!NetworkPolicy.shouldReadFromDiskCache(networkPolicy)) {
                    builder.noCache();
                }
                if (!NetworkPolicy.shouldWriteToDiskCache(networkPolicy)) {
                     builder.noStore();
                }
                cacheControl = builder.build();
            }
       }

      Request.Builder builder = new Request.Builder().url(uri.toString());
      if (cacheControl != null) {
            builder.cacheControl(cacheControl);
      }
        okhttp3.Response response = client.newCall(builder.build()).execute();
        int responseCode = response.code();
        if (responseCode >= 300) {
            response.body().close();
            throw new ResponseException(responseCode + " " + response.message(), networkPolicy,responseCode);
      }
        boolean fromCache = response.cacheResponse() != null;
        ResponseBody responseBody = response.body();
        return new Response(responseBody.byteStream(), fromCache, responseBody.contentLength());
    }
    //关闭App时,如果有缓存,关闭DiskLruCache;
    @Override public void shutdown() {
        if (cache != null) {
            try {
                cache.close();
            } catch (IOException ignored) {}
        }
    }
}

通过上面的代码已经构建出来一个OkHttp3downloader了,现在只需要将它加载到Picasso中去执行就好了;(注意:构建的picasso实例为一个单例,所以需要在Application中去创建这个实例,然后在调用的地方获取picasso单例即可);我是这样写的:

Picasso picasso = new Picasso.Builder(this)
        .downloader(new OkHttp3Downloader(new OkHttpClient()))
        .build();
Picasso.setSingletonInstance(picasso);

调用的时候这样写:

picasso.with(context).load("Path").into(imageView);

好了,Picasso的本地缓存说完了,



Picasso的使用技巧

添加listener:当你的使用picasso加载图片失败的时候,可以通过listener把失败原因打印

Picasso picasso = new Picasso.Builder(this)
        .listener(new Picasso.Listener() {
            @Override
            public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
                  //图片加载失败时的操作
            }
        })
        .loggingEnabled(true)// 打log
        .indicatorsEnabled(true)// 分辨不同的路径的价值的图片;
        .build();

回调:当图片加载成功和失败时的回调;

 picasso.with(this)
       .load("path")
       .into(imageView, new Callback() {
          @Override
          public void onSuccess() {    }
          @Override
          public void onError() {    }
});

Picasso的相关内容就说完了,如果大家有问题请在评论中指出;


推荐一篇文章: 使用Picasso加载带饼状进度条的图片

作者:Torang
链接:http://www.jianshu.com/p/9b93737bfa88
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值