Android 图片加载框架Picasso基本使用和源码完全解析(巨细无比)

澳门新葡亰手机版 13

说到Picasso,相信Android开发人员绝不陌生,它是Square公司开发的一款图片加载神器。使用过它的coder绝对是爱不释手:对它本身而言,轻量安全,有效加载图片并防止OOM;对我们开发者来说,简单方便,一行代码搞定图片加载。因此它备受Android开发人员的钟爱。

写在之前

关于它的更多好处优点,相信不用我介绍你也非常的清楚,在这里我们废话不多说,直接的进入主题来讲解它的使用和从源码的角度解析它的加载原理。

原本打算是每周更新一篇博文,同时记录一周的生活状态,但是稍微工作忙一点就顾不上写博客了。悲催
还是说下最近的状况,最近两周一直在接公司申请的计费点,
沃商店,银贝壳,微信等等,然后就是不停的被人催促催促,真是一个头两个大。在这期间项目组还搞了个App会员登录系统,接受第三方登录,然后应用到现有的App当中,然后又是一阵狂Coding。
说道第三方登录,那必然会包含第三方用户信息,比如头像,昵称等,原本项目中就使用了Picasso框架,之前也没有太深入的研究它,借此机会就认真的研究了一下它的源码实现,由此产生了这篇博文。

Picasso基本使用

一 工程引入

在我们的项目build.gradle中添加对Picasso框架的依赖:

compile 'com.squareup.picasso:picasso:2.5.2'

在这里我使用的是2.5.2的最新版本。

二 添加权限

因为加载图片需要访问网络,由此我们在Manifest中添加访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

三 创建加载图片布局文件

在我们的MainActivity的布局文件中添加一个Button和一个ImageView:

澳门新葡亰手机版 1

四 MainActivity中点击加载图片

在这里我们点击Button让它加载一张百度Logo的图片并显示在ImageView控件中。

澳门新葡亰手机版 2

五 加载图片

点击Button加载图片,来看结果:

澳门新葡亰手机版 3

ok,已加载出来了,但是我们到底做了什么呢?

正文

基本加载

其实我们所做的事情非常的简单,那就是在Button的点击事件中添加一行代码:

Picasso.with(MainActivity.this).load(url).into(headerImage);

没错就是一行代码搞定图片加载。至于它是怎么实现的,我们会在后面的源码分析中详细的解析它,现在来看看它的其他使用。

说到Picasso,相信Android开发人员绝不陌生,它是Square公司开发的一款图片加载神器。使用过它的coder绝对是爱不释手:对它本身而言,轻量安全,有效加载图片并防止OOM;对我们开发者来说,简单方便,一行代码搞定图片加载。因此它备受Android开发人员的钟爱。

占位图

不光加载图片是非常简单的事情,而且还可以在加载过程中使用占位图,可以很友好的告诉用户它正在加载,而不是加载中显示空白的界面。

Picasso.with(MainActivity.this)
.load(url)
.placeholder(R.mipmap.ic_launcher)
.into(headerImage);

使用placeholder为尚未加载到图片的ImageView设置占位图,这是一种友好的显示方式。

澳门新葡亰手机版 4

关于它的更多好处优点,相信不用我介绍你也非常的清楚,在这里我们废话不多说,直接的进入主题来讲解它的使用和从源码的角度解析它的加载原理。

异常图

不光可以设置占位图,而且还可以在图片加载不出来,或是找不到要加载的图片后,可以为ImageView设置异常图:

Picasso.with(MainActivity.this)
       .load(url)
       .placeholder(R.mipmap.ic_launcher)
       .error(R.drawable.error)
       .into(headerImage);

使用error可以为加载异常的ImageView设置异常图,修改我们的图片URL,使它无法获取到正确的图片地址,然后来看结果:

澳门新葡亰手机版 5

Picasso基本使用

一 工程引入

在我们的项目build.gradle中添加对Picasso框架的依赖:

compile 'com.squareup.picasso:picasso:2.5.2'

在这里我使用的是2.5.2的最新版本。

二 添加权限

澳门新葡亰手机版,因为加载图片需要访问网络,由此我们在Manifest中添加访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

三 创建加载图片布局文件

在我们的MainActivity的布局文件中添加一个Button和一个ImageView:

澳门新葡亰手机版 6

四 MainActivity中点击加载图片

在这里我们点击Button让它加载一张百度Logo的图片并显示在ImageView控件中。

澳门新葡亰手机版 7

五 加载图片

点击Button加载图片,来看结果:

澳门新葡亰手机版 8

ok,已加载出来了,但是我们到底做了什么呢?

转换器

不仅如此,我们还可以对加载到的图片进行重新调整,比如改变图片的大小,显示形状等,可以使用transform方法,例如:

首先我们先自定义一个Transformation:

private class customTransformer implements Transformation{

        @Override
        public Bitmap transform(Bitmap source) {
            //在这里可以对Bitmap进行操作,比如改变大小,形状等

            return source;
        }
        @Override
        public String key() {
            return null;
        }
    }

然后在transform方法中进行处理:

Picasso.with(MainActivity.this)
        .load(url)
        .placeholder(R.mipmap.ic_launcher)
        .transform(new customTransformer())
        .error(R.drawable.error)
        .into(headerImage);

这样的话就可以对图片进行一定意义上的控制和选择,使它更加符合我们的需求。

当然Picasso中还有很多其他的应用,比如可以设置加载大小,使用resizeDimen方法,填充方式使用centerCrop,fit等等,大家如果有需要的话可以自己尝试使用。这里就不要一一的介绍了。

基本加载

其实我们所做的事情非常的简单,那就是在Button的点击事件中添加一行代码:

Picasso.with(MainActivity.this).load(url).into(headerImage);

没错就是一行代码搞定图片加载。至于它是怎么实现的,我们会在后面的源码分析中详细的解析它,现在来看看它的其他使用。

Picasso 源码解析

ok,上面介绍了Picasso的部分基础使用,非常的简单,一行代码搞定你的所需,那么下面我们从源码的角度来解析下它到底是怎么实现我们的图片加载和使用的。

以下面最简洁的加载为示例:

Picasso.with(MainActivity.this).load(url).into(headerImage);

占位图

不光加载图片是非常简单的事情,而且还可以在加载过程中使用占位图,可以很友好的告诉用户它正在加载,而不是加载中显示空白的界面。

Picasso.with(MainActivity.this)
.load(url)
.placeholder(R.mipmap.ic_launcher)
.into(headerImage);

使用placeholder为尚未加载到图片的ImageView设置占位图,这是一种友好的显示方式。

澳门新葡亰手机版 9

with

首先Picasso会调用静态with方法,那么我们来看看with方法是怎么实现的:

澳门新葡亰手机版 10

由上面的源码我们可以看到,在with方法中主要做了一件事,那就是返回一个Picasso实例,当然这个实例也不是那么简单的创建的,为了防止Picasso的多次创建,这里使用了双重加锁的单例模式来创建的,主要目的是为了保证线程的安全性。但是它又不是直接的使用单例模式创建的,在创建实例的过程中使用了Builder模式,它可以使Picasso在创建时初始化很多对象,以便后期使用,那么我们就来看看这个Builder是怎么操作的:

澳门新葡亰手机版 11

在Builder的构造方法中就只是获取到当前应用级别的上下文,也就说明了Picasso是针对应用级别的使用,不会是随着Activity或是Fragment的生命周期而产生变化,只有当当前的应用退出或是销毁时Picasso才会停止它的行为。

那么接下来看下build方法中做了哪些操作呢:

澳门新葡亰手机版 12

这里代码也是很简单,主要是初始化了downloader,cache,service,dispatcher等几个实例变量,而这几个变量值也是已设置的,如源码:

  public Builder downloader(Downloader downloader) {
      if (downloader == null) {
        throw new IllegalArgumentException("Downloader must not be null.");
      }
      if (this.downloader != null) {
        throw new IllegalStateException("Downloader already set.");
      }
      this.downloader = downloader;
      return this;
    }

    public Builder executor(ExecutorService executorService) {
      if (executorService == null) {
        throw new IllegalArgumentException("Executor service must not be null.");
      }
      if (this.service != null) {
        throw new IllegalStateException("Executor service already set.");
      }
      this.service = executorService;
      return this;
    }

    public Builder memoryCache(Cache memoryCache) {
      if (memoryCache == null) {
        throw new IllegalArgumentException("Memory cache must not be null.");
      }
      if (this.cache != null) {
        throw new IllegalStateException("Memory cache already set.");
      }
      this.cache = memoryCache;
      return this;
    }

    ...

这些设置就像我们平常使用AlertDialog一样,货到到Builder之后分别进行设置就行。

ok,我们现在来看看初始化中几个非常重要的变量:

异常图

不光可以设置占位图,而且还可以在图片加载不出来,或是找不到要加载的图片后,可以为ImageView设置异常图:

Picasso.with(MainActivity.this)
       .load(url)
       .placeholder(R.mipmap.ic_launcher)
       .error(R.drawable.error)
       .into(headerImage);

使用error可以为加载异常的ImageView设置异常图,修改我们的图片URL,使它无法获取到正确的图片地址,然后来看结果:

澳门新葡亰手机版 13