Android深入android菜鸟笔记

Glide加载Gif动画播放速度过慢的问题

2019-12-05  本文已影响0人  李发糕

Glide版本3.7 目前不清楚4及以上版本是否有同样的问题
今天使用glide播放gif发现播放的速度很慢,在ios或者其他地方都没有这种问题。
跟踪源码查找发现,与播放速度相关的是每一帧的延时时间:

private void loadNextFrame() {
        if (!isRunning || isLoadPending) {
            return;
        }
        isLoadPending = true;

        gifDecoder.advance();
        long targetTime = SystemClock.uptimeMillis() + gifDecoder.getNextDelay();//获取一帧的延时时间
        DelayTarget next = new DelayTarget(handler, gifDecoder.getCurrentFrameIndex(), targetTime);
        requestBuilder
                .signature(new FrameSignature())
                .into(next);
    }
public int getDelay(int n) {
        int delay = -1;
        if ((n >= 0) && (n < header.frameCount)) {
            delay = header.frames.get(n).delay;//从解析出的gifheader中获取此帧延时时间
        }
        return delay;
    }

而在解析gif的过程中:

int delayInHundredthsOfASecond = readShort();
// TODO: consider allowing -1 to indicate show forever.
if (delayInHundredthsOfASecond < MIN_FRAME_DELAY) { //这个值为3
     delayInHundredthsOfASecond = DEFAULT_FRAME_DELAY;//这个值为10
}
header.currentFrame.delay = delayInHundredthsOfASecond * 10;        

当解析每帧数据时,如果此帧延时<30毫秒,则会被赋值为100毫秒。debug发现ui小哥哥给我的gif正好是20毫秒每帧延迟,所以播放很慢。这就尴尬了。
因为不太想下载源码修改,这里偷懒直接用了反射去修改。

Glide.with(this)
            .load(lotteryBean.getBanner_pic())
            .asGif()
            .into(new SimpleTarget<GifDrawable>(){
        @Override
        public void onResourceReady(GifDrawable resource, GlideAnimation<? super GifDrawable> glideAnimation) {
            try {
                Field field = GifDecoder.class.getDeclaredField("header");
                field.setAccessible(true);
                GifHeader header = (GifHeader) field.get(resource.getDecoder());
                Field field2 = GifHeader.class.getDeclaredField("frames");
                field2.setAccessible(true);
                List frames = (List) field2.get(header);
                if (frames.size()>0){
                    Field delay = frames.get(0).getClass().getDeclaredField("delay");
                    delay.setAccessible(true);
                    for (Object frame : frames) {
                        delay.set(frame,20);//这里直接给修改成了20
                    }
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }
            mBannerImage.setImageDrawable(resource);
            resource.setLoopCount(Integer.MAX_VALUE);
            resource.start();
        }
    });

不过这种方式不太灵活,只能算是应急吧。尝试了反射替换decoder相关类,感觉比较麻烦,Glide的很多类都无法在包外调用,暂时不了了之TT。
欢迎有好的方案的老哥留言~

上一篇 下一篇

猜你喜欢

热点阅读