InteractionManager源码阅读笔记

2019-02-23  本文已影响0人  zhangwx89

InteractionManager的直接翻译是交互管理器,在react-native的文档里,其作用描述为:"Interactionmanager 可以将一些耗时较长的工作安排到所有互动或动画完成之后再进行。这样可以保证 JavaScript 动画的流畅运行。"

我们最常用这个类的场景是:从A页面跳转到B页面,然后想让B页面的网络请求或者页面刷新工作放到过场动画结束后再去做,这时可以用InteractionManager的runAfterInteractions函数来实现。

那么问题来了,如果A页面有一个循环不停止的动画,这时候再跳转B页面,B页面为了转场动画的顺畅使用了runAfterInteractions,但由于A页面的循环动画而永远无法进入回调闭包,这个问题怎么解决呢?

react-native官方已经考虑到了,在Animated类里面的loop方法,有这么一段话:"In addition, loops can prevent VirtualizedList-based components from rendering more rows while the animation is running. You can pass isInteraction: false in the child animation config to fix this."。虽然这段话不是在解决我们说的问题,但是所提到的isInteraction属性,我们可以通过Animated的源码,看到这个属性是用来干嘛的。

由此可见,这个isInteraction属性是用来控制是否创建句柄的。

那么关键的来了,InteractionManager.createInteractionHandle()和InteractionManager.runAfterInteractions()之间的具体关系是什么样的呢?

我们可以看看InteractionManager的源码

先看这一对函数:

一个是创建句柄一个是清除句柄,其实创建句柄很简单,所谓的句柄就是全局变量_inc自增后的结果,然后加入了_addInteractionSet的集合。清除句柄,就是把handle从_addInteractionSet中移除,加入_deleteInteractionSet。那么整个InteractionManager是如何运作起来的呢?runAfterInteractions中的回调是如何被调用的?这其实最核心的部分是在_scheduleUpdate里面:

_scheduleUpdate主要是处理了InteractionManager的deadline,然后调用了_processUpdate:

如上图所示,第一个红框里面其实就是InteractionManager最核心的部分。还记得刚才的createInteractionHandle和clearInteractionHandle么,其实整个InteractionManager就是实现了生产者消费者模型。第二个红框部分,其实就是去执行runAfterInteractions里面的闭包回调。我们最后再看runAfterInteractions:

参数task最终加入了_taskQueue中,而这个_taskQueue会在_processUpdate中被遍历执行。

用一个很通俗易懂的方法来解释InteractionManager,比如我们去面馆吃面,跟老板说我要一碗面(createInteractionHandle),然后我们就找个位子等老板把面端上来了(runAfterInteractions(()=>{console.log('吃面')})),过了一阵子老板面做好了,于是端上面(clearInteractionHandle),我们就吃到面了。那么又有个疑问了,为啥InteractionManager要设计的这么复杂呢?直接存一下回调,然后触发回调不就好了么。这就好比我们出去吃面,不可能吃光面一样。比如我们要吃一碗雪菜肉丝面,那么流程就得这样了:

最后,我们看一下react-native里面会有哪些地方默默的为我们createInteractionHandle呢?

一共就这两处,第一处就是创建动画的时候,官方文档上也说了可以用来延迟耗时操作,保证转场动画流畅。第二处是这个PanResponder,官方文档也做了解释,保证手势响应顺畅。但其实大家在理解了上面吃面的例子后,也可以扩展一下自己的思维,灵活的运用InteractionManager。

上一篇下一篇

猜你喜欢

热点阅读