Glide专注于平滑滚动的Android图像加载和缓存库

Glide

Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。

Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。Glide的Api是如此的灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。

虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。

性能

Glide 充分考虑了Android图片加载性能的两个关键方面:

  • 图片解码速度
  • 解码图片带来的资源压力

为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。

Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:

  • 自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
  • 积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
  • 深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。

兼容性

  • 最低 Android SDK 要求:Glide v4 要求最低 API 级别为 14。
  • 编译 Android SDK:Glide v4 要求使用 API 26 或更高版本进行编译。

如果您需要支持旧版本的 Android,请考虑使用 [Glide v3][14],它基于 API 10 运行,但目前已不再积极维护。

  • OkHttp 3.x:有一个名为“okhttp3-integration”的可选依赖项,请参阅[文档页面][23]。
  • Volley:有一个名为“volley-integration”的可选依赖项,请参阅[文档页面][24]。
  • 圆形图片CircleImageView/CircularImageView/RoundedImageView 在使用 TransitionDrawable.crossFade().thumbnail().placeholder() 结合使用)和动画 GIF 时存在 [问题][18],请使用 [BitmapTransformation][19](.circleCrop() 将在 v4 中可用)或 .dontAnimate() 来修复此问题。
  • 巨型图片(地图、漫画):Glide 可以通过降低采样率来加载巨型图片,但不支持缩放和平移 ImageView,因为它们需要特殊的资源优化(例如平铺)才能正常工作而不会引发 OutOfMemoryError

构建

使用 gradle 构建 Glide 非常简单:

shell 复制代码
git clone https://github.com/bumptech/glide.git
cd glide
./gradlew jar

注意:请确保您的 Android SDK 已安装 Android 支持库,并且您的 $ANDROID_HOME 环境变量
指向 SDK,或者在根项目中添加 local.properties 文件,并在其中添加 sdk.dir=... 行。

API

Glide 使用简明的流式语法API,这是一个非常棒的设计,因为它允许你在大部分情况下一行代码搞定需求:

language 复制代码
Glide.with(fragment)
    .load(myUrl)
    .into(imageView);

取消加载同样很简单:

language 复制代码
Glide.with(fragment).clear(imageView);

尽管及时取消不必要的加载是很好的实践,但这并不是必须的操作。实际上,当 Glide.with() 中传入的 Activity 或 Fragment 实例销毁时,Glide 会自动取消加载并回收资源。

在 Application 模块中的使用

在 Application 模块中,可创建一个添加有 @GlideModule 注解,继承自 AppGlideModule 的类。此类可生成出一个流式 API,内联了多种选项,和集成库中自定义的选项:

language 复制代码
package com.example.myapp;

import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

生成的 API 默认名为 GlideApp ,与 AppGlideModule 的子类包名相同。在 Application 模块中将 Glide.with() 替换为 GlideApp.with(),即可使用该 API 去完成加载工作。

language 复制代码
GlideApp.with(fragment)
   .load(myUrl)
   .placeholder(placeholder)
   .fitCenter()
   .into(imageView);

可以访问 Glide 的 generated API 页面来获得更多信息。

定制请求

Glide 提供了许多可应用于单一请求的选项,包括变换、过渡、缓存选项等。

默认选项可以直接应用于请求上:

language 复制代码
Glide.with(fragment)
  .load(myUrl)
  .placeholder(placeholder)
  .fitCenter()
  .into(imageView);

选项也可以通过 RequestOptions 类来在多个请求之间共享:

language 复制代码
RequestOptions sharedOptions = 
    new RequestOptions()
      .placeholder(placeholder)
      .fitCenter();

Glide.with(fragment)
  .load(myUrl)
  .apply(sharedOptions)
  .into(imageView1);

Glide.with(fragment)
  .load(myUrl)
  .apply(sharedOptions)
  .into(imageView2);

对于更高级的使用场景,通过使用 Glide 的 generated API,Glide 的 API 还可以被更深度地定制以包含自定义的选项。

在 ListView 和 RecyclerView 中的使用

在 ListView 或 RecyclerView 中加载图片的代码和在单独的 View 中加载完全一样。Glide 已经自动处理了 View 的复用和请求的取消:

language 复制代码
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    String url = urls.get(position);
    Glide.with(fragment)
        .load(url)
        .into(holder.imageView);
}

对 url 进行 null 检验并不是必须的,如果 url 为 null,Glide 会清空 View 的内容,或者显示 placeholder Drawable 或 fallback Drawable 的内容。

Glide 唯一的要求是,对于任何可复用的 View 或 Target ,如果它们在之前的位置上,用 Glide 进行过加载操作,那么在新的位置上要去执行一个新的加载操作,或调用 clear() API 停止 Glide 的工作。

language 复制代码
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    if (isImagePosition(position)) {
        String url = urls.get(position);
        Glide.with(fragment)
            .load(url)
            .into(holder.imageView);
    } else {
        Glide.with(fragment).clear(holder.imageView);
        holder.imageView.setImageDrawable(specialDrawable);
    }
}

对 View 调用 clear() 或 into(View),表明在此之前的加载操作会被取消,并且在方法调用完成后,Glide 不会改变 view 的内容。如果你忘记调用 clear(),而又没有开启新的加载操作,那么就会出现这种情况,你已经为一个 view 设置好了一个 Drawable,但该 view 在之前的位置上使用 Glide 进行过加载图片的操作,Glide 加载完毕后可能会将这个 view 改回成原来的内容。

这里的代码以 RecyclerView 的使用为例,但规则同样适用于 ListView。

非 View 目标

除了将 Bitmap 和 Drawable 加载到 View 之外,你也可以开始异步加载到你的自定义 Target 中:

language 复制代码
Glide.with(context
  .load(url)
  .into(new CustomTarget<Drawable>() {
    @Override
    public void onResourceReady(Drawable resource, Transition<Drawable> transition) {
      // Do something with the Drawable here.
    }

    @Override
    public void onLoadCleared(@Nullable Drawable placeholder) {
      // Remove the Drawable provided in onResourceReady from any Views and ensure 
      // no references to it remain.
    }
  });

使用自定义 Target 有一些陷阱,所以请务必阅读 目标文档页 的详细内容。

后台线程

在后台线程加载图片也是直接使用 submit(int, int):

language 复制代码
FutureTarget<Bitmap> futureTarget =
  Glide.with(context)
    .asBitmap()
    .load(url)
    .submit(width, height);

Bitmap bitmap = futureTarget.get();

// Do something with the Bitmap and then when you're done with it:
Glide.with(context).clear(futureTarget);

如果你不想让 Bitmap 和 Drawable 自身在后台线程中,你也可以使用和前台线程一样的方式来开始异步加载:

language 复制代码
Glide.with(context)
  .asBitmap()
  .load(url)
  .into(new Target<Bitmap>() {
    ...
  });

开发

按照 构建 部分中的步骤设置项目,然后根据需要编辑文件。
[Android Studio][26] 会干净地导入 Glide 的源代码和测试文件,这是使用 Glide 的推荐方式。

要在 Android Studio 中打开项目:

  1. 转到 文件 菜单或 欢迎屏幕
  2. 点击 打开...
  3. 导航到 Glide 的根目录。
  4. 选择 setting.gradle

许可证

BSD,MIT 部分和 Apache 2.0。详情请参阅 LICENSE 文件。

关于项目

Glide是一个快速高效的Android图片加载库,注重于平滑的滚动。Glide提供了易用的API,高性能、可扩展的图片解码管道(decode pipeline),以及自动的资源池技术。
Apache-2.0
Javascript
34,965
6179
1027
2013-07-09
2025-10-11

增长趋势 - stars