Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践

首先,动图的格式有gif,webp。其中同质量的动图 webp会比gif更小,所以动图优先还是使用webp的。

然后如果当页面有很多动图,类似于抖音的个人中心页面的三个tab,页面的一个RecyclerView全是动图,就需要考虑针对动图的优化了。

我们以抖音为例。

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

两个页面在一个HorizontalScrollView(ViewPager的offsetLimit很大的话也是类似的)内部包着,相当于会有多个页面在内存中,如果不作处理,页面绘制帧率就会很低。gif动图也许会很卡。

1.我们先来解决页面帧率的问题:

刚刚我们说到了,activity含有多个fragment的时候,一般会使用ViewPager对fragment做托管,好处是简单,方便。但是为了首页使用tab+viewPager的架构方式,一般会将ViewPager的offsetLimit设置的很大(默认为1,也就是默认缓存左右两个fragment,最多有3个页面),默认将所有的fragment都缓存在内部。

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

这种情况其实很危险,如果类似于抖音5个页面(上图4个,还有左滑的一个)都在缓存中,而且多个页面都在绘制的时候,系统性能消耗是十分恐怖的。观察方案可以开启开发者模式内,GPU呈现模式分析,条形图。每一个柱状图对应绘制每一帧的耗时。

划重点!其实默认不作处理的话,哪些都在内存的fragment加载后都会不断绘制。也就是不管你看不看的见,那些动图,都一直在那,从没停止动过。那么类似抖音这种有大量动图的app必须对页面的动图做出处理,否则页面的帧率堪忧。

好在Fresco这个框架还是足够强大的(为啥不用glide后面再说),我们可以控制gif动或者不动。

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

如上我们可以在controlListener里面对常量animatable赋值,

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

然后通过控制animatable的播放与否,实现动图是否“动”(绘制)。

以上的类在如果在feedViewHolder内部,我们还需要在Adapter上维护一个队列,然后通过Adapter来维护在RecyclerView上所有的动图。

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

通过WeakReference保护,是为了防止意外的内存泄漏。

这样我们可以在页面可见与否的时候控制页面内所有的动图播放与否。

类似道理,当我们保证仅仅可见的页面在绘制的话,对于页面帧率的优化提高是极大的。

其实让View不再绘制有一个简单粗暴的方法,页面不可见,设置页面根View不可见,不可见了也就不会去绘制了。但是这个涉及到一个问题:Fresco由于内存管理策略,不会对动图缓存。页面重新可见的时候,相当于需要重新加载所有的动图。对于动图decode的时候是十分费时的事情,重新decode加载,页面的负担会更大。此方法需要慎重。

2.我们再来探索怎么提高动图的帧率:

也就是让动图加载的更快,更流畅。

一开始的时候发现IOS与Android在同一个页面的时候,Android的动图就是一卡一卡的(类似看在线电影,网络环境不好的感觉),但是ios的就很顺畅。

撇开手机的定位(毕竟睾贵的IOS,我这是渣渣红米)作比较都是耍流氓,我又去拿了一个华为的P10,三星的S9作为比较。发现表现最好的是华为P10。三星S9卡的和我的红米差不多。要知道S9是目前Android旗舰啊,不应该性能这么战5啊。仔细对比几部手机的参数,发现三星是2k屏幕,红米和华为都是P10。嗯,2k的同样面积占据更大的分辨率,自然需要更大的性能去渲染(可以看做是1080的4倍)。将三星的手机分辨率更改为1080P,测试发现和P10差不多,稍稍好些。

划重点gif加载帧率是和手机屏幕分辨率有关的。

当然就算好手机的帧率高些,但是还是达不到丝般顺滑的体验。Android表示不服,于是继续探索该怎么优化这个gif帧率。我首先发现有一个参数

《Fresco库的gif,webp动图帧率,以及页面帧率优化探索实践》

这个参数的作用是在decode的时候优先加载第一帧,把第一帧先填上去,然后再开播,这样加载动图的时候看上去加载的很快。嗯,也就是看上去很快,其实动图播放的还是会很卡。

继续探索。尝试更改ResizeOptions的初始分辨率,scaleType等等,还是不行。

这时候我已经想放弃Fresco了,为啥你就这么慢啊。看到google“官方”的glide,体积小,加载快balabala。

于是调研Glide替换,然后坑爹的事情发生了———–glide支持gif,webp图片,但是特么不支持webP的动图。我们项目里面都是webp的动图啊。血崩。第三方支持让glide播放webp动图的方案不稳定。decode方案还是从fresco里面提取出来的。一首凉凉送给glide。。。。

继续死磕Fresco,从init,到加载,到播放。。。终于一日灵光乍现,发现Fresco的版本号是1.2,一看最新的版本都已经是1.9了。死马当活马医的升级了Fresco(升级Fresco是一部血泪史,各种复杂的依赖关系,暂且不表)。

居然终于有效果了!!!动图不卡了。惊不惊喜?意不意外?~      播放帧率很高,和IOS一样的顺滑。总结的经验就是感觉动图很卡,可以先检查项目里面的Fresco的版本,尝试升级也许有意外收获哦~~~

当然也带来了其他的问题,依赖关系,导致其他各种库崩溃就不说了。

问题1、滑动卡顿。

这个不能忍啊,不能你播放不卡,但是操作很卡啊。但是这个难不住我,尝试在RecycleView里面的onScorll方法里面增加方法

addOnScrollListener(new RecyclerView.OnScrollListener() {

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

                if (newState == RecyclerView.SCROLL_STATE_IDLE) {

                    Fresco.getImagePipeline().resume();

                }else {

                   Fresco.getImagePipeline().pause();

               }

            }

});

于是滑动不卡了,只是滑动的时候不能加载动图了。顺畅一比~

怀疑是decode方案策略更新了,原先是另起线程,异步操作,更新的方案是优先加载,同步操作。待调研~

问题2、上文中的首帧优先加载失效了

这个问题是偶然发现的,目前还没发现原因,这里先做个记录吧。为啥不着急解决呢?因为我感觉不到啊!一下子动图就开播了,怀疑是作为默认方案了。所以设置为true和不加这个代码没有区别了。待调研~

页面帧率优化是一个长期的工作,未完待续~

    原文作者:我讲笑话没人笑
    原文地址: https://www.jianshu.com/p/4b1433a77055
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞