一个关于RN的InteractionManager简介。
这几天在着手开发react-native的项目,写了个页面,发现页面跳转的过程中非常卡,很纳闷我代码写的挺规范(自我感觉不是一般的好😄)怎么会产生这样的现象,后经查阅文档了解到,原因是我在页面载入的过程中调了服务端接口,正确做法是把调接口逻辑写在
1 |
|
里,因此决定好好研究下InteractionManager。
1、基本内容
InteractionManager是一个可以提升用户体验和交互效果的模块,它可以让一些任务在比较耗时的操作或者动画完成后执行,这样能够保证我们的js动画比较平滑的运行,比如导航跳转新页面。
对大多数React Native应用来说,业务逻辑是运行在JavaScript线程上的,这是React应用所在的线程,也是发生API调用、以及处理触摸事件等操作的线程。更新数据到原生支持的视图是批量进行的, 并且在事件循环每进行一次的时候被发送到原生端,这一步通常会在一帧时间结束之前处理完(如果一切顺利的话)。如果JavaScript线程有一帧没有及时响应,就被认为发生了一次丢帧。 例如,你在一个复杂应用的根组件上调用了this.setState,从而导致一次开销很大的子组件树的重绘,可想而知,这可能会花费200ms也就是整整12帧的丢失。 此时,任何由JavaScript控制的动画都会卡住。只要卡顿超过100ms,用户就会明显的感觉到。
这种情况经常发生在Navigator的切换过程中:当你push一个新的路由时,JavaScript需要绘制新场景所需的所有组件,以发送正确的命令给原生端去创建视图。由于切换是由JavaScript线程所控制, 因此经常会占用若干帧的时间,引起一些卡顿。有的时候,组件会在componentDidMount函数中做一些额外的事情,这甚至可能会导致页面切换过程中多达一秒的卡顿。
InteractionManager里面包含的方法:
-
runAfterInteractions: 里面的函数在所有的交互和动画完成之后运行。返回一个可取消的 promise。
-
createInteractionHandle: 通知管理器有某个交互开始了。
-
clearInteractionHandle: 通知管理器有某个交互已经结束了。
-
setDeadline: 设置延迟时间,会调用setTimeout方法挂起并且阻塞所有没有完成的任务,然后在eventLoopRunningTime到设定的延迟时间后,然后执行setImmediate方法进行批量执行任务。
这些方法和js原生的某些方法的比较:
- window.requestAnimationFrame: 执行一个动画,并告诉浏览器在下次重绘之前调用指定的回调函数更新动画, 该方法需传入一个回调函数,此回调在下一次重绘前执行。
如果想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame。
-
setImmediate/setTimeout: 设置延迟执行任务的时间,可能会影响到正在执行的动画。
-
runAfterInteractions: 延迟执行任务,不会影响到正在执行的动画效果。
2、源码解析
1 |
|
整个InteractionManager就是实现了生产消费者模型。