Android 玩转Glide4---进阶篇

前言

系列文章专栏: 玩转Glide4
基础使用篇:Android 玩转Glide4—基础使用篇
进阶使用篇:Android 玩转Glide4—进阶使用篇
Transformation篇:Android 玩转Glide4—Transformation篇

概述

基础使用篇中我们简单介绍了Glide4的使用,以及相对于Glide3的变化。
本篇进阶篇,将会介绍预加载,生命周期,加载监听,下载图片等方面的内容。

预加载—preload()

Glide加载图片会自动判断图片是否在缓存中,以此来决定直接读取缓存还是直接下载。
但是如果我希望提前对图片进行一个预加载,比如有一张网络大图,进入页面最开始不需要展示,但是需要展示的时候我们想立刻展示出来,而不需要等待。
怎么办呢?----可以使用preload()方法。

public Target<TranscodeType> preload(int width, int height) //指定加载图片的宽和高

public Target<TranscodeType> preload() //加载图片的原始尺寸

preload()方法的用法非常简单,直接使用它来替换into()方法即可,如下代码:

 Glide.with(this)
            .load(ConstUrl.ImgGif)
            .preload()

我们可以在页面打开的时候先preload()预加载,然后需要显示的into()接口,如下代码:

 preload.setOnClickListener {
            Glide.with(this)
                .load(ConstUrl.ImgGif)
                .into(ivPreload)
        }

在这里插入图片描述

加载监听—listener()

如果一张网络图片未按照预期中显示出来,我们就需要知道它的加载状态。listener()用来监听Glide加载图片的状态失败还是完成。

Glide.with(this).load(ConstUrl.ImgOne).listener(object : RequestListener<Drawable> {
            override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                Log.e(TAG, "onLoadFailed", e)
                return false
            }

            override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                Log.i(TAG, "onResourceReady")
                resource.to
                return false
            }
        }).into(ivListener)

不过还有一点需要处理,onResourceReady()方法和onLoadFailed()方法都有一个布尔值的返回值,返回false就表示这个事件没有被处理,还会继续向下传递,返回true就表示这个事件已经被处理掉了,从而不会再继续向下传递。

图片下载—submit()

如果没有图片框架的帮助下我们去显示一张网络图片,通常的做法都是异步线程下载字节流保存到本地为File,然后再显示这个File。
对于Glide来说,将图片保存在本地有很多中方法,比如上面的listener方法的onResourceReady回调中,我们可以拿到Drawable.toBitmap()转为Bitmap对象,然后再转为字节流存在File中。
然而Glide给我们提供了一个更加便捷的方法submit()。
相对与preload(),submit()只会下载图片,不会加载,也不会缓存图片,需要我们拿到下载完成图片文件自己去操作。

 public FutureTarget<TranscodeType> submit() //下载原始尺寸的图片

 public FutureTarget<TranscodeType> submit(int width, int height) //指定下载图片的尺寸

调用了submit()方法后会返回一个FutureTarget对象,然后Glide会在后台开始下载图片。接下来需要我们调用FutureTarget的get()方法去获取下载图片文件,如果此时图片还没有下载完,那么get()方法就会阻塞住,一直等到图片下载完成才会有值返回。
因此submit()必须在异步线程中执行,代码如下:

  download.setOnClickListener {
            Thread(Runnable {
                val taget = Glide.with(this).asFile().load(ConstUrl.ImgOne).submit()
                val imgFile = taget.get()
                runOnUiThread {
                    Glide.with(this).load(imgFile).into(ivDownload)
                    Toast.makeText(this, imgFile.path, Toast.LENGTH_LONG).show()
                }
            }).start()
        }

在这里插入图片描述

生命周期—Target

Gilde的into()方法,通常我们都是传ImageView的,但是查看源码就知道它还能传Target类型的参数。
你会发现Target中有两个重写函数onResourceReady,onLoadFailed跟listener很相似,实际上他们的作用也几乎一致,那么他们的区别是什么呢?
你可以理解Target中的这两个函数为listener中分发函数,主要便于我们自定义Target时使用。
分发体现在:如果我们在RequestListener的onResourceReady()方法中返回了true,那么就不会再回调Target的onResourceReady()方法了。

DrawableImageViewTarget

Gilde4中封装好了一些ViewTarget,我们可以很方便的调用,我们以DrawableImageViewTarget为例子。
比如我们需要在加载图片的时候先显示一个进度条,加载完成后进度条消失,代码如下


        val simpleTarget = object : DrawableImageViewTarget(ivInto) {
            override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                super.onResourceReady(resource, transition)
                progressBar.hide()
            }

            override fun onLoadStarted(placeholder: Drawable?) {
                super.onLoadStarted(placeholder)
                progressBar.show()

            }

            override fun onLoadFailed(errorDrawable: Drawable?) {
                super.onLoadFailed(errorDrawable)
            }

            override fun onLoadCleared(placeholder: Drawable?) {
                super.onLoadCleared(placeholder)
            }
            
            override fun onStart() {
                super.onStart()
            }

            override fun onStop() {
                super.onStop()
            }

            override fun onDestroy() {
                super.onDestroy()
            }

        }
        val optionInto = RequestOptions()
            .skipMemoryCache(true)
            .diskCacheStrategy(DiskCacheStrategy.NONE)
        Glide.with(this).load(ConstUrl.ImgGif).apply(optionInto).into(simpleTarget)
自定义Target—CustomViewTarget

我们可以让Glide加载出来的图片不显示到ImageView上吗?答案是肯定的,这就需要用到自定义Target功能。

我们简单实现如下布局控件,我们要在左边显示网路图片,右边显示ic_launcher。代码如下:

  <LinearLayout
            android:id="@+id/targetLayout"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            app:layout_constraintStart_toStartOf="@id/ivInto"
            app:layout_constraintTop_toBottomOf="@id/ivInto">

            <ImageView
                android:id="@+id/iv1"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1" />

            <ImageView
                android:id="@+id/iv2"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>
class MyTarget constructor(view: View) : CustomViewTarget<View, Drawable>(view) {
    override fun onLoadFailed(errorDrawable: Drawable?) {

    }

    override fun onResourceCleared(placeholder: Drawable?) {

    }

    override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
        view.findViewById<ImageView>(R.id.iv1).setImageDrawable(resource)
    }
}


Glide.with(this).load(ConstUrl.ImgOne).apply(optionInto).into(MyTarget(targetLayout))

在这里插入图片描述

Glide组件—GlideModule

由于Glide内部网络加载使用的是HttpURLConnection,相较我们经常使用的Okhttp性能上差距较大,因此我们经常会使用Okhttp替换网络组件。
4.x的自定义组件相较于3.x改动较大:

  1. 自定义模块类上使用注解即会自动注册,可以不用通过Manifest注册。
  2. 在应用模块中需要继承AppGlideModule实现,在中则必须要继承LibraryGlideModule实现,而非3.x的GlideModule
  3. 注册调用replace方法的类改成了Registry而非Glide。

如我们实现一个Okhhtp网络组件。

1.引入Okhttp依赖和Glide官方的Okhttp集成库。
//okhttp3
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
//Glide官方扩展库,https://github.com/bumptech/glide/tree/master/integration/okhttp3
implementation 'com.github.bumptech.glide:okhttp3-integration:4.3.1'
2.应用模块中继承AppGlideModule实现。
@GlideModule
class GlideConfigModule :AppGlideModule() {
    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        //super.registerComponents(context, glide, registry)
        registry.replace(GlideUrl::class.java, InputStream::class.java, OkHttpUrlLoader.Factory())
    }
}

实际上官方的Okhttp集成库,已经实现了上面的代码OkHttpLibraryGlideModule,我们只需要引入依赖即可。

@GlideModule
public final class OkHttpLibraryGlideModule extends LibraryGlideModule {
  @Override
  public void registerComponents(
      @NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
  }
}

代码

GitHub: https://github.com/DeMonDemo/Glide4Img

参考

郭霖的专栏—Glide最全解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值