Android 入门(十四)Glide

748 阅读5分钟

要求:会使用 Glide 进行图片加载

Glide 是一个第三方的类库,所以我们需要在 build.gradle 中添加依赖

implementation 'com.github.bumptech.glide:glide:4.9.0'

还有我们需要进行网络请求,在 manifest 中申请网络权限也是不能省的

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

Glide 简单使用

用了 Glide 后想要将一张图片加载到 ImageView 非常简单,下面的一行代码就可以搞定。

findViewById(R.id.load_image_btn).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Glide.with(v).load(imgUrl).into(mImageView);
    }
});

首先 Glide.with() 方法用于创建一个加载图片的实例,with() 方法可以接收 Context、Activity、FragmentActivity、Fragment 还有 View,我们的选择非常广泛。如果调用的地方不在有 View 的场景里,我们还可以获取当前应用程序的 ApplicationContext 传入 with()。还有需要注意的是,传入的实例会决定 Glide 的生命周期。

然后是 load() 方法,load() 方法的重载也非常多,几乎囊括所有可用的图片资源类型。包括网络图片、本地图片、应用资源、二进制流、Uri对象等等。

最后就是 into() 方法,into() 方法就很简单了,传入想要显示的 ImageView 即可。

其他的配置

要进行其他的配置,如添加占位符、改变图片大小、形状等等,Glide 都封装在 RequestOptions 类中。

RequestOptions options = new RequestOptions()
        .circleCrop()   // 将图片剪切为圆形
        .override(Target.SIZE_ORIGINAL) // 使用原始图片的尺寸
        // 占位符,在图片还没下载好之前显示的图片
        .placeholder(R.drawable.ic_launcher_foreground)
        .error(R.drawable.ic_launcher_background)   // 图片加载错误之后现在的图片
        .diskCacheStrategy(DiskCacheStrategy.NONE)  // 禁止图片缓存
        .skipMemoryCache(true); // 禁止图片内存缓存
        
Glide.with(v)
        .load(imgUrl)
        .apply(options) 
        .into(mImageView);

需要详细介绍的是缓存机制,Glide 的缓存分成了「内存缓存」和「硬盘缓存」,他们都是默认开启的,如果想要禁用,分别加入 skipMemoryCache() 和 diskCacheStrategy() 方法即可。其中 diskCacheStrategy 可传入的参数有:

  • DiskCacheStrategy.NONE: 表示不缓存任何内容。
  • DiskCacheStrategy.DATA: 表示只缓存原始图片。
  • DiskCacheStrategy.RESOURCE: 表示只缓存转换过后的图片。
  • DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
  • DiskCacheStrategy.AUTOMATIC: 表示让Glide根据图片资源智能地选择使用哪一种缓存策略(默认选项)。

RequestOptions 还有更多的配置使用方法,自己查看 Api 就好。

加载指定格式

我们前面说过 load() 方法中可以传入各种图片资源(包括 GIF),但是有时候我们想指定加载格式,目前有四种 asGif()、asBitmap()、asFile()、asDrawable(),分别用于强制指定加载 GIF、Bitmap、File、Drawable 格式。

需要注意的是他们都要写在 load() 方法之前,否则就会报错。因为 load() 方法会得到一个 RequestBuilder 类,而 asxxx() 方法是 RequestManage 才有的。

回调与监听

into() 方法

我们现在只能将图片展示到 ImageView 中,我们还能利用 Glide 获取图片之后用于别的用途吗?当然可以,我们前面讲了 into() 方法可以传入一个 ImageView,其实还能接收 Target 类,Glide 中的 Target 功能多样且复杂,我们了解一下 SimpleTarget 的用法:

SimpleTarget<Drawable> simpleTarget = new SimpleTarget<Drawable>() {
    @Override
    public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
        imageView.setImageDrawable(resource);
    }
};

public void loadImage(View view) {
    Glide.with(this)
         .load(imgUrl)
         .into(simpleTarget);
}

可以看到,我们创建可一个 SimpleTarget 的实例,并且指定他的范型为 Drawable,然后重写了 onResourceReady 方法,并在其中我们获取到了 Glide 加载出来的 Drawable 对象。有了这个对象我们就可以做任何事情了。

preload() 方法

preload() 方法 主要是对图片进行预加载,这个方法是需要替换 into() 的。所以在执行了 preload() 之后,还需要调用 into() 进行图片展示。

Glide.with(this)
     .load(imgUrl)
     .preload();
     
Glide.with(this)
     .load(imgUrl)
     .into();

submit() 方法

submit() 方法给我们提供了访问缓存图片的方法,也是需要替换 into() 方法。调用了该方法之后会立即返回一个 FutureTarget 对象,我们调用 FutureTarget 的 get() 方法就可以得到图片文件。但是如果图片没有下载完,get() 会一直堵塞,所以需要放到子线程中执行,避免堵塞 UI 线程。

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            FutureTarget<File> target = Glide.with(MainActivity.this)
                    .asFile()
                    .load(imgUrl)
                    .submit();
            // 如果图片还没下载完 get() 方法会一只堵塞
            final File file = target.get();
            // do something...
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this,
                    file.getPath(), Toast.LENGTH_LONG).show();
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}).start();

listener() 方法

listener() 方法可以用来监听 Glide 加载图片的状态,前面几个方法都是需要替换 into() 来使用的,listener 是结合 into() 一起使用的,当然也可以结合 preload() 使用。

Glide.with(v)
        .load(imgUrl)
        .listener(new RequestListener<Drawable>() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, 
                                        Target<Drawable> target, boolean isFirstResource) {
                return false;
            }
            @Override
            public boolean onResourceReady(Drawable resource, Object model, 
                                           Target<Drawable> target, DataSource dataSource, 
                                           boolean isFirstResource) {
                return false;
            }
        })
        .into(mImageView);

在 into() 之前串接一个 listener() 方法即可,我们可以看到有 onLoadFailed() 和 onResourceReady() 方法,当图片加载失败时会回调前者,加载成功则会回调后者。需要注意的是,两个方法都需要返回一个布尔值,如果返回 false 表示这个事件还会继续往下传递,返回 true 就表示这个事件已经被处理了,不会再往下传递。

图片变换

图片变换的用法非常简单,只需要在 RequestOptions 中拼接 transforms() 方法,并将想要进行的图片操作作为参数传入 transforms() 即可。详细的使用方法可以看郭神的 Android图片加载框架最全解析(五),Glide强大的图片变换功能。当然还可以使用第三方库,glide-transformations

其实 Glide 已经帮我们实现了几种操作,比如 CenterCrop、FitCenter、CircleCrop等。将他们替换 transforms() 方法即可。

参考

Android图片加载框架最全解析(八),带你全面了解Glide 4的用法