RN Flatlist减少render次数

rn的诟病来自于本身的框架底层问题。
设计之初,以安卓为例,居然只从一个activity里渲染各种pages,于是乎留存在了各种性能上的问题,out of memory,甚至无法打印this,页面堆栈导致的物理返回键需要由一个公用父处理什么的……问题多多。

可这些其实都是小问题,问题比较严重的却是一个很常见的且该存在的深度检查导致的问题。如果说浅比较state比较节省性能,那么就不应该出现setState({a:0})时会导致整个组件的重新render。

这个问题虽然严重,但是更为严重的却是任何子组件都是一个实实际际的object,也许你会说,肯定都是obj,这个没毛病。确实,但是在flatlist中你发现这个问题,即每次渲染都会重新return出新对象,这次100,下次还是100……你就会真正的觉得react应该把这个地方作为优化项。

为什么呢?比如item1中存在一个会变化的数值,那么当我手动变化该数值时在flatlist中会出现什么情况呢?我们为了让flatlist能检测到我们的数值变化,我们设置extraData为this.state。

1:我变更了100条数据其中的一条数据的数值。
2:页面发生了render周期。
3:因为设置了extraData进行数据检测,所以遍历比较完当前的整个state和下一次state之间的不同,进行数据更新。
4:flatlist开始重新render出每个item。
5:整个页面重新载入数据。

整个过程在测试中81条数据的话,在 小米8se手机的骁龙720 下几近需要1.3秒!这是一个恐怖的事情,如果是这样,那么81*2,*n那该怎么办?

我们对待重新render每个item毫无办法,但是好在我们知道这个item其实结构并不复杂,顶多算是牺牲内存。
然后我们发现去掉extraData的时候,整个过程变快了,达到了ms级。所以我们考虑从主动为每个即将render的item进行数据比较,来决定这个item是不是应该重新render。

于是我们在shouldComponent里获取当前item尚未变化的视图里的数值,然后和state中的值进行比较来决定是否render(其实怎么说item都会render,这里只不过是去掉由setState引发的多次render)。

至此,81条数据的情况下开始变得十分顺畅,测试更多条同样很顺利。

本以为事情会就此结束。
如果你有长得一毛一样的数据,且你这个时候要使用key来提前指定控件pos,减少开销的话,你就会发现item会瞎跳,因为rn为了节省性能,实际只渲染当前屏幕,所以发生了这种情况。

如果你在使用如上方式解决了卡顿。然后你要使用onScroll方法,你就会发现变化单个item的数值的时候又卡了……
兴许如果真有人遇到这种情况,早就抄起原生把自己的list封装出来用了。我也没有心情再去深究了,于是我在外面包了层scrollView,确实不卡了,可是,我发现flat的scrollTo类似的任何方法都没法生效了……
于是我们需要干嘛呢?我们只能使用scrollview的scrollTo来代替flat的scrollTo的类似方法,于是我们要为每一个item提前计算好它的startY,如果有必要,我们还将测量它的item高度,来算得endY,为下一个item的startY做打算。

然后我们终于解决了这些问题,可是问题又来了。

如果我们得flatlist实际上也来自一个组件,它的根组件有个同级组件需要主动改变flatlist某个item的值。


结构示例:
pages:主页面
cate:flatlist组件
item:flatlist的item组件
cat:发起变化的同级组件


于是,我们怎么做到在pages里发起item的变更呢,因为我们拿到了cate的flatlist组件我们也拿不到所以item对象。这也是比较鸡肋的地方,flat树结构真的没做好。
在cate里把每个item渲染的时候都把它们加入到一个叫itemGroup的数组。我们在cat的时候判断itemGroup是否可用,如果是,那么我们遍历itemGroup,执行我们写好在item里的refresh。总的来说,还是会卡一点儿,但是,貌似别无他法了。

水逆退散吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值