问题出现
在使用Glide加载一个聊天页面的表情包。之前的表情包都是循环播放,没有任何问题。现在加入了猜拳和骰子,这类表情包需要播放到1次末尾的时候停止播放,进而展示当前随机到的内容是什么。
现在使用的方案是使用只会播放1次的gif进行加载。下面是我的加载代码:
GlideApp.with(tv.context)
.asGif()
.load(msgDto.msg)
.override(dp2px(tv.context, 25), dp2px(tv.context, 25))
.into(imageView)
那么现在的问题是什么呢?
- 加载Loop count = 0的gif,循环播放
- 加载loop count = 1的gif,会出现有的播放一次,有的循环播放
解决问题
尝试方案
我第一时间猜测是GIF图片的播放次数问题。因此我使用了ezgif.com ,Photoshop,在线PS等各种工具进行文件导出,尝试重新设置图片循环次数。
结果图片循环次数是加上了,但是Android不可以单次播放。(ios正常加载)
通常的排除法此时失效:
- iOS可用,Android不可以,可以排除图片的问题❓
- 其他播放一次的gif可以适配,这个只播放一次的gif适配不了,可以排除加载方式的问题❓
问题不难,真的折磨人。下面是解决思路:
问题原因
根本原因在于不同的GIF文件在制作时,对于“Loop Count(循环次数)”的元数据(Metadata)写入标准不一致,或者部分文件缺少该头部信息。
当Glide加载这些文件时,如果没有显式指定行为,GifDrawable 可能会根据缺省设置或者被复用的View状态,导致某些本该只播放一次的图变成了无限循环。
为了通过同一个语句完美支持“无限循环”和“只播放一次”的GIF,你需要显式地告诉 Glide:“请严格按照GIF文件原本定义的次数播放(Intrinsic)”。
下面可用的加载代码:
import com.bumptech.glide.load.resource.gif.GifDrawable
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
Glide.with(tv.context)
.asGif()
.load(msgDto.msg)
.override(dp2px(tv.context, 25), dp2px(tv.context, 25))
.listener(object : RequestListener<GifDrawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<GifDrawable>?,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: GifDrawable?,
model: Any?,
target: Target<GifDrawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
resource?.setLoopCount(GifDrawable.LOOP_INTRINSIC)
return false
}
})
.into(imageView)
基本可以解决很多问题。

发表回复