2022

Glide4.0只播放一次Gif以及监听播放完成的实现方法

2019-01-10  本文已影响0人  锐心凌志

前言
这篇blog主要记录一下最近刚好遇见的问题,要实现一个gif只播放一次并且要在gif播放完之后回调一下的需求,项目目前用的Glide是4.0版本,这个问题如果在Glide3.7上那么很好解决,网上有一大把的代码示例,但是在Glide4.0的版本上,怎么搜都搜不到类似的,只好自己想方法解决了,好了废话不多说。
解决方法
一般在Glide3.7的时候是这样解决的,
Glide.with(this)
.load("xxxurl")
.listener(new RequestListener<Integer, GlideDrawable>() {

                @Override
                public boolean onException(Exception arg0, Integer arg1,
                        Target<GlideDrawable> arg2, boolean arg3) {
                    return false;
                }

                @Override
                public boolean onResourceReady(GlideDrawable resource,
                        Integer model, Target<GlideDrawable> target,
                        boolean isFromMemoryCache, boolean isFirstResource) {
                    // 计算动画时长
                    GifDrawable drawable = (GifDrawable) resource;
                    GifDecoder decoder = drawable.getDecoder();
                    for (int i = 0; i < drawable.getFrameCount(); i++) {
                        duration += decoder.getDelay(i);
                    }
                    //发送延时消息,通知动画结束
                    handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,
                            duration);
                    return false;
                }
            }) //仅仅加载一次gif动画
            .into(new GlideDrawableImageViewTarget(imageview, 1));

但是在Glide4.0中,没法再直接获取GifDecoder对象了,原因是因为GlideDrawable不再提供这个方法了。
我这里是采用反射的方法获取到GifDecoder变量的,具体代码如下:
public static void loadOneTimeGif(Context context, Object model, final ImageView imageView, final GifListener gifListener) {
Glide.with(context).asGif().load(model).listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}

        @Override
        public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
            try {
                Field gifStateField = GifDrawable.class.getDeclaredField("state");
                gifStateField.setAccessible(true);
                Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
                Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
                gifFrameLoaderField.setAccessible(true);
                Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
                Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
                gifDecoderField.setAccessible(true);
                Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
                Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
                Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
                getDelayMethod.setAccessible(true);
                //设置只播放一次
                resource.setLoopCount(1);
                //获得总帧数
                int count = resource.getFrameCount();
                int delay = 0;
                for (int i = 0; i < count; i++) {
                    //计算每一帧所需要的时间进行累加
                    delay += (int) getDelayMethod.invoke(gifDecoder, i);
                }
                imageView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (gifListener != null) {
                            gifListener.gifPlayComplete();
                        }
                    }
                }, delay);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            return false;
        }
    }).into(imageView);
}

/**
 * Gif播放完毕回调
 */
public interface GifListener {
    void gifPlayComplete();
}

同时,因为我们采用的是反射,所以别忘了在你的proguard-rules.pro中加上Glide的反混淆规则,

Glide

-keep class com.bumptech.glide.** {*;}

好了,这样就大功告成啦~

上一篇 下一篇

猜你喜欢

热点阅读