一个能够提高用户体验和交互效果的模块InteractionMnager(交互管理器)es6
使用InteractionManager可让一些耗时的任务在交互操做或者动画完成以后进行执行,这样使用能够保证咱们的JavaScript的动画效果能够平滑流畅的执行。能够大大提高用户体验。好比:导航的转场动画web
对大多数React Native应用来讲,业务逻辑是运行在JavaScript线程上的。这是React应用所在的线程,也是发生API调用,以及处理触摸事件等操做的线程。更新数据到原生支持的视图是批量进行的,而且在事件循环每进行一次的时候被发送到原生端,这一步一般会在一帧时间结束以前处理完(若是一切顺利的话)。若是JavaScript线程有一帧没有及时响应,就被认为发生了一次丢帧。 例如,你在一个复杂应用的根组件上调用了this.setState,从而致使一次开销很大的子组件树的重绘,可想而知,这可能会花费200ms也就是整整12帧的丢失。此时,任何由JavaScript控制的动画都会卡住。只要卡顿超过100ms,用户就会明显的感受到。后端
属性方法浏览器
runAfterInteractions(task) 静态方法,在用户交互和动画结束之后执行任务 createInteractionHandle() 静态方法,建立一个句柄(处理器),通知管理器,某个动画或者交互开始了 clearInteractionHandle(handler:Handle) 静态方法,进行清除句柄,通知管理器,某个动画或者交互结束了。 setDeadline(deadline:number) 静态方法, 设置延迟时间,该会调用setTimeout方法挂起而且阻塞全部没有完成的任务,而后在eventLoopRunningTime到设定的延迟时间后,而后执行setImmediate方法进行批量执行任务 Events:CallExpression addListener:CallExpression
在应用开发中咱们能够以下进行执行任务异步
InteractionManager.runAfterInteractions(() => { //执行耗时的同步任务 });
该模块和其余相关的调度方法对比:函数
requestAnimationFrame():执行控制动画效果的代码
setImmediate/setTimeout():设置延迟执行任务的时间,该可能会影响到正在执行的动画
runAfterInteractions():延迟执行任务,该不会影响到正在执行的动画效果
触摸系统中的单点或者多点触控都是交互动做,耗时任务会在这些触摸交互动做执行完成以后或者取消之后回调runAfterInteractions()方法进行执行。oop
InteractionManager也容许应用在动画开始的时候经过createInteractionHandle()方法注册动画生成一个句柄,在结束的时候清除该句柄。fetch
var handle = InteractionManager.createInteractionHandle(); //执行动画 (`runAfterInteractions` tasks are queued) //动画执行结束 InteractionManager.clearInteractionHandle(handle); //动画清除以后,开始直接runAfterInteractions中的任务
runAfterInteractions任务也能够接收一个普通的回调函数或者一个带有gen方法而且返回一个Promise的PromiseTask对象。若是参数是PromiseTask对象,那么任务是异步执行的,也会阻塞。该会等着当前任务执行完毕之后才能执行下一个任务。动画
默认状况下,队列任务会一次性在setImmediate方法中批量执行。若是你经过setDeadline方法设置一个时间值,那么任务会在延迟该设定值时间进行执行。这时候会调用setTimeout方法进行挂起任务而且阻塞其余任务的执行。这样能够给触摸交互等操做留出时间更好的相应用户操做this
具体使用
InteractionManager.runAfterInteractions(() => { //执行耗时的同步任务 navigate("Redeem", { title: "积分兑换" }); })
或者
constructor(props) { super(props); this.state = { renderPlaceholderOnly: true } } render(){ if (this.state.renderPlaceholderOnly) { // Toast.loading("加载中...", 1); return self._renderPlaceholderView(); } return( ..... ) } componentDidMount = () => { InteractionManager.runAfterInteractions(() => { this.setState({ renderPlaceholderOnly: false }); }); };
定时器是一个应用中很是重要的部分。React Native实现了和浏览器一致的定时器Timer
提供以下方法
setTimeout, clearTimeout setInterval, clearInterval setImmediate, clearImmediate requestAnimationFrame, cancelAnimationFrame
setTimeout (fn, 1000) 和 setInterval (fn,1000)
和web中的意思同样,前者表示延迟1000毫秒后执行 fn 方法 ,后者表示每隔1000毫秒执行 fn 方法。
requestAnimationFrame(fn)和setTimeout(fn, 0)不一样,
前者会在每帧刷新以后执行一次,然后者则会尽量快的执行(在iPhone5S上有可能每秒1000次以上)。
setImmediate则会在当前JavaScript执行块结束的时候执行,就在将要发送批量响应数据到原生以前。注意若是你在setImmediate的回调函数中又执行了setImmediate,它会紧接着马上执行,而不会在调用以前等待原生代码。
Promise的实现就使用了setImmediate来执行异步调用。
注意点:
一、定时器功能比较简单,注意在es6中使用时,需铭记在unmount组件时清除(clearTimeout/clearInterval)全部用到的定时器。
二、可使用定时器实现一些普通功能:如短信倒计时等
三、对于一些须要延迟执行的特殊场景也可使用Timer,譬如:目前RN提供的fetch是没有提供设置超时时间的,若是客户端请求后端的一个接口,接口超时了(后端服务设置的超时时间为10s),那么RN界面就一直loading,也不能aborded。那么这时候咱们就能够巧妙的使用计时器,若是客户端发出的Request,时间大于某个值(5秒),那么咱们直接认为请求失败。
四、今天还发现一个使用setTimeout的场景,在列表页加载下一页的时候,若是接口响应很快,就不会出现loading的效果,这个时候为了有loading的效果,设置一个500毫秒的延时