Glide & Picasso 超详细对比

1.概览

图片库 Picasso Glide
版本 2.5.2 3.7.0
作者 square bumptech
时间 2012 2013
star 12k 12k
大小 121KB 476KB
方法数 849 2879

简单使用

还以这张老图为例:
大小739*417,32位色,全大小RBG_8888时占用内存约1203KB
Glide & Picasso 超详细对比_第1张图片

导入图片库

Picasso:

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

Glide:

  compile 'com.github.bumptech.glide:glide:3.7.0'
  compile 'com.android.support:support-v4:19.1.0'

现在v7(依赖v4)包基本上是标配,所以不一般不用再显式引入v4包

Java代码

Picasso:

Picasso.with(this).load(URL).into(ivPicasso);

Glide:

Glide.with(this).load(URL).into(ivGlide);

代码看上去差不多

最后因为我们加载的是网络上的图片,别忘了添加权限

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

ps:我的两个ImageView是相同的固定尺寸,并且比原图小

看一下效果吧:

Glide & Picasso 超详细对比_第2张图片

看出有什么差别了么

2.共性

  • 使用简单
    都可以通过一句代码可实现图片获取和显示。

  • 都支持webp格式的图片
    http://zhitu.isux.us/assets/img/imgSample/test-60.webp

    Glide & Picasso 超详细对比_第3张图片

  • 内存缓存
    默认都是LruCache 开启,都可以设置不使用内存缓存,如下
    Glide:

    Glide.with( context )
         .load( URL )
         .skipMemoryCache( true )
         .into( ivGlide);

    ps:如果第一次某个url时候没有skipMemoryCache( true ),后面带上了图片还是会被缓存到内存中

    Picasso:

    Picasso.with(this).
                    load(URL).
                    memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).
                    into(ivPicasso);

    MemoryPolicy.NO_CACHE:不从内存缓存中查找
    MemoryPolicy.NO_STORE:不存储到内存缓存中

  • 指定加载进内存的图片尺寸

    Picasso:

    .resize(300, 200);

    Glide:

    .override(300, 200);
  • CenterCrop
    都用:

    .centerCrop();
    
  • 变换
    Picasso:

    .transform(new CircleTransform())

    Glide:

    .transform(new CircleTransform(context))

    在返回前对图片做一些处理工作

  • 设置默认占位图和错误占位图

    .placeholder(R.drawable.placeholder)
    .error(R.drawable.imagenotfound)
    
  • 优先级

    .priority()

    如App 页面中 Banner 的优先级高于 Icon 时就很适用

  • 支持多种数据源
    支持多种数据源,网络、本地、资源、Assets 等

  • 支持多种 Displayer
    不仅仅支持 ImageView,同时支持自定义Target

3.重要差别

默认的Bitmap格式
上面的图可以看出来Glide加载出来的图片质量是比Picasso差的,这是因为Picasso加载Bitmap的格式是RGB_8888,Glide默认Bitmap的格式是RGB_565;这也就是说Picasso每个像素只用四个字节,而Glide每个像素用两个字节,占用内存减少一半,差的图片质量对应低内存占用。

下面是在内存快照中找到的对应图片在内存中的大小:
Glide & Picasso 超详细对比_第4张图片
Picasso:1232652字节,约1203KB

Glide & Picasso 超详细对比_第5张图片
Glide:180000字节,约176KB

发现Glide所占的内存不是Picasoo的一半,居然更少。
可以通过自定义Module来让Glide加载ARGB_8888格式的图片,这看实际的需求吧。

默认加载到内存的图片大小
Picasso不管ImageView的大小都会加载全尺寸的图片到内存中,让GPU来重绘大小。而Glide会根据ImageView的大小来加载不同尺寸的图片到内存中。这时当ImageView的大小比原图小很多的时候,Glide的优势就会非常的明显。

其实Picasso也能实现相应的功能,只是显得比较笨拙。

  • 如果ImageView的大小是match_patent或者确定值的话,可以通过
 Picasso.with(this).load(URL).fit().into(ivPicasso);

此时查看内存:
Picasso:
这里写图片描述

Glide:
这里写图片描述

发现大约是两倍,这就对了

  • 如果ImageView的大小是wrap_content
    这时候使用fit()就不管用了,Picasso无法加载出图像,你需要调用resize()方法来确定大小
Picasso.with(this).load(URL).resize(400,230).into(ivPicasso);

这样导致的问题是,我们需要自己手动计算出ImageView的大小

ps:这里必须说明的一个问题是,Glide在wrap_content的情况下加载一个全大小的图片进入内存。

硬盘缓存
Picasso:

我分别在xml指定ImageView 为400px *230px 和 200px *130px ,让Picasso来加载同一张图片,然候查看缓存
Glide & Picasso 超详细对比_第6张图片
额,发现三个文件最大的那个是图片本身,是全尺寸的,另外一个存的是这张图片对应的HTTP响应头,journal是DiskLruCache的日志文件。
其实重点是只缓存了一个全尺寸的的图片,但是同时也验证了Picasso的缓存是借助于okhttp实现的。

Glide:
进行同样的操作:

Glide & Picasso 超详细对比_第7张图片

发现也是有三个文件,但是这其中两个都是图片,尺寸和之前加载的图片大小都相同,journal同样是DisLruCache的日志文件。也就是说默认情况Glide为每种尺寸的ImageView都缓存一次。

Glide这样做的好处是加载显示非常快,而Picasso需要在显示之前重新调整图片的大小,导致有一些延迟

另外,Glide也支持其他的硬盘缓存策略:

  • DiskCacheStrategy.NONE
    什么也不缓存
  • DiskCacheStrategy.SOURCE
    只缓存原始大小的图片,和Picasso一样

  • DiskCacheStrategy.RESULT
    默认的缓存策略,只缓存经过压缩后的图片,不缓存原始的图片;这种情况下每有一种尺寸的ImageView都要从网络重新下载,即使后来ImageView的尺寸比之前小。

  • DiskCacheStrategy.ALL caches all versions of the image
    缓存所有的图片,包括原始的和各种尺寸的图片。下载全尺寸的图片,以后不需要再从网络下载,只需要对原始的图片调整成合适的大小,然后再缓存。

Glide.with(this).load(URL).diskCacheStrategy(DiskCacheStrategy.ALL).into(ivGlide);

并发线程数改变策略

Picasso:
根据网络类型的切换来改变线程数

//class PicassoExecutorService
void adjustThreadCount(NetworkInfo info) {
    if (info == null || !info.isConnectedOrConnecting()) {
      setThreadCount(DEFAULT_THREAD_COUNT);
      return;
    }
    switch (info.getType()) {
      case ConnectivityManager.TYPE_WIFI:
      case ConnectivityManager.TYPE_WIMAX:
      case ConnectivityManager.TYPE_ETHERNET:
        setThreadCount(4);
        break;
      case ConnectivityManager.TYPE_MOBILE:
        switch (info.getSubtype()) {
          case TelephonyManager.NETWORK_TYPE_LTE:  // 4G
          case TelephonyManager.NETWORK_TYPE_HSPAP:
          case TelephonyManager.NETWORK_TYPE_EHRPD:
            setThreadCount(3);
            break;
          case TelephonyManager.NETWORK_TYPE_UMTS: // 3G
          case TelephonyManager.NETWORK_TYPE_CDMA:
          case TelephonyManager.NETWORK_TYPE_EVDO_0:
          case TelephonyManager.NETWORK_TYPE_EVDO_A:
          case TelephonyManager.NETWORK_TYPE_EVDO_B:
            setThreadCount(2);
            break;
          case TelephonyManager.NETWORK_TYPE_GPRS: // 2G
          case TelephonyManager.NETWORK_TYPE_EDGE:
            setThreadCount(1);
            break;
          default:
            setThreadCount(DEFAULT_THREAD_COUNT);
        }
        break;
      default:
        setThreadCount(DEFAULT_THREAD_COUNT);
    }
  }

Glide:
根据CPU的核数

//class GldieExecutor

public static int calculateBestThreadCount() {
        // We override the current ThreadPolicy to allow disk reads.
        // This shouldn't actually do disk-IO and accesses a device file.
        // See: https://github.com/bumptech/glide/issues/1170
        ThreadPolicy originalPolicy = StrictMode.allowThreadDiskReads();
        File[] cpus = null;
        try {
            File cpuInfo = new File(CPU_LOCATION);
            final Pattern cpuNamePattern = Pattern.compile(CPU_NAME_REGEX);
            cpus = cpuInfo.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File file, String s) {
                    return cpuNamePattern.matcher(s).matches();
                }
            });
        } catch (Throwable t) {
            if (Log.isLoggable(TAG, Log.ERROR)) {
                Log.e(TAG, "Failed to calculate accurate cpu count", t);
            }
        } finally {
            StrictMode.setThreadPolicy(originalPolicy);
        }

        int cpuCount = cpus != null ? cpus.length : 0;
        int availableProcessors = Math.max(1, Runtime.getRuntime().availableProcessors());
        return Math.min(MAXIMUM_AUTOMATIC_THREAD_COUNT, Math.max(availableProcessors, cpuCount));
    }

4.Glide特性

图片加载会和Activity和Fragment的生命周期保持一致
Glide.with()函数除了支持Context外,还支持Fragment和Activity,如在onPause后暂停加载,在onResume后恢复加载

载Gif动画

加载视频
这个支持本地视频,可以将本地视频的第一帧解码成一张静态图片。

缩略图

配置图片显示的动画
Picasso只有一种动画:fading in

你可能感兴趣的:(Android图片)