Glide 加载Gif 导致cpu居高不下的解决办法

最近抽空整理成了Module方式 GitHub地址
GlideGifLibs

最近由于要所有图片上支持gif的展示,结果在界面上显示3张gif图后cpu飙升到了90%,一会手机就烫手了。想了很多种办法 比如监听view的显示或者隐藏状态然后再来控制GIF的播放与暂停。但是都未能很好的实现。网上也查询了很多关于view的进入或退出屏幕的监听,但是都未能找到。要么就是不能通用的进行判断。搞了几天也没找到解决办法就想到了为何不去问问Glide作者呢。问之前我先搜索了下是否有人已经提出过该问题,结果发现已经有人提出过该问题。而且也给出了解决方案连接如下连接地址

我下载了连接中的demo发现cpu控制在30%左右。而且发现当gif图的控件移除屏幕后会自动停止gif的播放进入时会重新播放。原理大概是因为FrameSequenceDrawable继承至Drawable.drawable与View相关联 查看ImageView源码发现

	@Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
        if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
            mDrawable.setVisible(getVisibility() == VISIBLE, false);
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        // Only do this for old apps pre-Nougat; new apps use onVisibilityAggregated
        if (mDrawable != null && sCompatDrawableVisibilityDispatch) {
            mDrawable.setVisible(false, false);
        }
    }

在view被添加上屏幕和移除屏幕时都会重新设置drawable的显示状态达到不在屏幕区域中的GIF图停止播放。

然后根据Glide作者提供的自定义解码器sample来编写我们自己的Gif解码器 现在我们选用FrameSequence。

public class GifDecoder implements ResourceDecoder<InputStream,FrameSequence> {

    @Override
    public Resource<FrameSequence> decode(InputStream source, int width, int height) throws IOException {
        try {
            FrameSequence fs = FrameSequence.decodeStream(source);
            return new SimpleResource<>(fs);
        } catch (Exception e) {
            throw new IOException("Cannot load gif from stream", e);
        }
    }

    @Override
    public String getId() {
        return "com.move.gifdecoder";
    }
}
public class GifDrawableTranscoder implements ResourceTranscoder<FrameSequence,FrameSequenceDrawable> {

    @Override
    public Resource<FrameSequenceDrawable> transcode(Resource<FrameSequence> toTranscode) {
        FrameSequenceDrawable drawable = new FrameSequenceDrawable(toTranscode.get());
        return new MyResource<>(drawable);
    }

    @Override
    public String getId() {
        return "";
    }
}
public class GifSoftwareLayerSetter<T> implements RequestListener<T, FrameSequenceDrawable> {

    @Override
    public boolean onException(Exception e, T model, Target<FrameSequenceDrawable> target, boolean isFirstResource) {
        ImageView view = ((ImageViewTarget<?>) target).getView();
        if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
            view.setLayerType(ImageView.LAYER_TYPE_NONE, null);
        }
        return false;
    }

    @Override
    public boolean onResourceReady(FrameSequenceDrawable resource, T model, Target<FrameSequenceDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
        ImageView view = ((ImageViewTarget<?>) target).getView();
        if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
            view.setLayerType(ImageView.LAYER_TYPE_SOFTWARE, null);
        }
        return false;
    }
}

调用方法

fun displayGif(context: Context, url: String, targeView: ImageView) {
            val uri = Uri.parse(url)
            getRequestManager(context)
                    .using(Glide.buildStreamModelLoader(Uri::class.java, context), InputStream::class.java)
                    .from(Uri::class.java)
                    .`as`(FrameSequence::class.java)
                    .transcode(GifDrawableTranscoder(), FrameSequenceDrawable::class.java)
                    .sourceEncoder(StreamEncoder())
                    .cacheDecoder(FileToStreamDecoder(GifDecoder()))
                    .decoder(GifDecoder())
                    .listener(GifSoftwareLayerSetter<Uri>())
                    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                    .load(uri)
                    .into(targeView)
        }

这样就能用我们自己写的解码器去加载gif。

最近又写朋友问我要demo 趁着有空就顺手写了一下附上链接地址
demo地址

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值