最近抽空整理成了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地址