Picasso从使用到源码解析

Picasso从使用到源码解析一、使用Picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能。仅仅只需要一行代码就能完全实现图片的异步加载:Picasso.with(context).load(url).into(imageView);Picasso不仅实现了图片异步加载的功能,还解决了An
摘要由CSDN通过智能技术生成

Picasso从使用到源码解析


一、使用

Picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能。仅仅只需要一行代码就能完全实现图片的异步加载:

Picasso.with(context).load(url).into(imageView);

Picasso不仅实现了图片异步加载的功能,还解决了Android中加载图片时需要解决的一些常见问题:

  1. 在adapter中需要取消已经不在视野范围的ImageView图片资源的加载,否则会导致图片错位,Picasso已经解决了这个问题。
  2. 使用复杂的图片压缩转换来尽可能的减少内存消耗
  3. 自带内存和硬盘二级缓存功能

同时它还支持以下功能:

1. 图片转换:转换图片以适应布局大小并减少内存占用

Picasso.with(context).load(url).resize(50, 50).centerCrop().into(imageView);

这里的50单位是px,使用dp则换成下面这句,并定义相应资源文件。
resizeDimen(R.dimen.iv_width,R.dimen.iv_height)

2. 自定义转换:

public class CustomTransformation implements Transformation {
   
  @Override public Bitmap transform(Bitmap source) {
    Bitmap result;
    //一些处理
    if (result != source) {
      source.recycle();//一定要recycle!!!!
    }
    return result;
  }
  @Override public String key() { return "key"; }
}
//使用
Picasso.with(context).load(url).transform(new CustomTransformation()).into(imageView);

3. 空白或者错误占位图片: picasso提供了两种占位图片,未加载完成或者加载发生错误的时需要一张图片作为提示。

Picasso.with(context)
    .load(url)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.placeholder_error)
    .into(imageView);

4. 资源文件的加载:除了加载网络图片picasso还支持加载Resources, assets, files, content providers中的资源文件。

Picasso.with(context).load(R.drawable.***).into(imageView1);
Picasso.with(context).load(new File(...)).into(imageView2);

二、解析

1.with(context)方法

//Picasso.java
 public static Picasso with(Context context) {
    if (singleton == null) {
      synchronized (Picasso.class) {
        if (singleton == null) {
          singleton = new Builder(context).build();
        }
      }
    }
    return singleton;
  }

可以看出这是一个DCL(双重检查锁)实现的单例模式,其中单例的实例化又是通过Builder模式实现。接下来看下Builder中做了哪些工作。

//Picasso.java
public static class Builder {
   
    private final Context context;
    private Downloader downloader;//下载器
    private ExecutorService service;//线程池
    private Cache cache;//缓存方式
    private Listener listener;//Linstener为一接口,只有onImageLoadFailed(...)方法
    private RequestTransformer transformer;//变换器
    private List<RequestHandler> requestHandlers;
    private Bitmap.Config defaultBitmapConfig;

    private boolean indicatorsEnabled;
    private boolean loggingEnabled;

    /** Start building a new {@link Picasso} instance. */
    public Builder(Context context) {
      if (context == null) {
        throw new IllegalArgumentException("Context must not be null.");
      }
      this.context = context.getApplicationContext();
    }

    ...

    public Picasso build() {
      Context context = this.context;

      if (downloader == null) {
        downloader = Utils.createDefaultDownloader(context);
      }
      if (cache == null) {
        cache = new LruCache(context);//cache默认LruCache
      }
      if (service == null) {
        service = new PicassoExecutorService();
      }
      if (transformer == null) {
        transformer = RequestTransformer.IDENTITY;//默认不转换
      }

      Stats stats = new Stats(cache);

      Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);

      return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,
          defaultBitmapConfig, indicatorsEnabled, loggingEnabled);
    }
  }

  ...
 }

Builder中主要对Picasso的参数进行了初始化工作,下边看下其中Downloader的初始化:

//Utils.java
static Downloader createDefaultDownloader(Context context) {
    try {
      Class.forName("com.squareup.okhttp.OkHttpClient");
      return OkHttpLoaderCreator.create(context);
    } catch (ClassNotFoundException ignored) {
    }
    return new UrlConnectionDownloader(context);
  }

可以看出Downloader会通过反射判断是否能够使用OkHttp,不能则使用HttpURLConnection,不过这里的包名是OkHttp3以前的写法,现在我们都是使用OkHttp3了,而OkHttp3的包名是okhttp3.OkHttpClient,所以即使你在项目中引用了OkHttp3,Picasso还是会把HttpUrlConnection当作下载器来下载图片的,这个问题估计Picasso会在以后的版本中修正吧,接着看下service的初始化:

//PicassoExecutorService.java  继承ThreadPoolExecutor 
PicassoExecutorService() {
    super(DEFAULT_THREAD_COUNT, DEFAULT_THREAD_COUNT, 0, TimeUnit.MILLISECONDS,
        new PriorityBlockingQueue<Runnable>(), new Utils.PicassoThreadFactory());
  }

service其实就是一个线程池,其中DEFAULT_THREAD_COUNT=3,所以这里构造了一个仅仅只有3个核心线程并使用优先级队列调度的线程池。接下来的就是Picasso的构造方法了:

//Picasso.java
Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,
      RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,
      Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {
    this.context = context;
    this.dispatcher = dispatcher;
    this.cache = cache;
    this.listener = listener;
    this.requestTransformer = requestTransformer;
    this.defaultBitmapConfig = defaultBitmapConfig;

    int builtInHandlers = 7; // Adjust this as intern
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值