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

来源:互联网 发布:好用的桌面便签 知乎 编辑:程序博客网 时间:2024/05/23 21:49

最近由于要所有图片上支持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。

0 0
原创粉丝点击