react 360消息传递原理解析
react vr中文网:www.vr-react.com
react vr qq群:481244084
示例源码 github:https://github.com/LiuC520/ReactVR/
早起react 360是叫react vr的,后来facebook改成了react 360,原来的好多东西包括原理和模块都重写了,原来介绍了react vr 消息传递原理,里面有些原理已经修改了。
现在我重新来倒着讲一下消息传递的原理,这次更浅显易懂些。
开发者头条:react vr 原理解析
开发者头条:React VR 视频源码解析
开发者头条:react vr 消息传递原理解析
首先举个例子,我想实现在react 一边发送消息,在html里面能接收到,举个例子,我要在html的入口文件中加个loading,然后在js解析完毕再关闭loading,来优化体验?
1、首先我们需要在html中添加如下的代码:
loading html.png
也就是添加html5的loading div,并给了个旋转的动画,只要加载页面就显示loading。
接下来我们来如何让动画在加载了页面以后消失。
2、在上面html中我们可以看到,先加载的是client的bundle文件,里面有一个init的方法,然后才是具体执行这个init初始化方法,传递的参数是index.bundle文件,还有要挂载的div,其他的一些配置(资源路径等等)。
这时间我们还按照上一篇文章里讲的worker来操作,因为这是搬运工,来回搬运数据的,也就相当于快递的中转站。
寄件方(刘成)把快件给了快递员,快递员再打个包给收件方(刘成的女朋友)。同时收件方(刘成的女朋友)也可以成为寄件方,再把新的快件给快递员(刘成),快递员打个包再寄回去。
不同的是,这个快递不一样,里面有好多小的商品,刘成给他的女朋友买了好多东西,有牙刷、有牙膏、手机、电脑、还有西瓜,这时间快递员就需要按照不同的类型把这些东西打包放好放到一个大箱子里面,这样才不会乱,要不然女朋友收到这么一堆乱七八糟的东西,直接就扔了分手了。
开个玩笑,其实react 360的消息机制就是这样的,只不过react 360的工人跟原来的不一样了,原来是直接聘请了(new)一个工人(worker),
直接在client里面调用下面的方法就可以了,具体接收到的参数就放到onVRMessage方法里面来操作
vr.rootView.context.worker.addEventListener('message',onVRMessage);//接受消息的在react vr那边直接 postMessage({ type: "sceneLoadStart"})
function onVRMessage(e) {
switch (e.data.type) {
case 'sceneChanged':
if (window.playerCamera.zoom != 1) {
window.playerCamera.zoom = 1;
window.playerCamera.updateProjectionMatrix();
}
break;
case 'sceneLoadStart':
document.getElementById('loader').style.display = 'block';//设置html的div属性
break;
case 'sceneLoadEnd':
document.getElementById('loader').style.display = 'none';
break;
default:
return;
}
}
//-------------------------------接受消息-e-------------------------------
而现在react 360重构了以后,就好像新建一个工作站,搞了一块儿底盘,然后建立了工作室(Executor),工人都在工作室里面
原来的工人在conext上下文中可以直接取到,现在需要用下面的方法才能让loading消失。
client里面的方法如下图
WX20180528-234401@2x.png
3、运行时
r360.runtime.executor._worker.addEventListener('message', onVRMessage);
现在的工人不在上下文中直接取了,
而是在运行时里面,你也可以自己传递一个executor到运行时里面,具体怎么搞,以后再给大家讲解,也就是你可以自定义传递的类型和方法。
这个runtime是干嘛的呢?他是react vr的主要逻辑了,他发送数据给executor,在内存中构建node节点,同时还告诉Compositor怎样渲染一切的东西。
有点儿像CEO的感觉,总管一切,executor就像team leader,这个leader把数据包装成blob,然后给工人去传递。
其他的暂时不讲,至于如何在内存中构建node节点,如何告诉Compositor去渲染,后面单独开文章再讲。
4、worker
可以看到运行时里面新建了一个ReactExecutorWebWorker,这个工人类呢里面有几个方法,也就是team leader有几个方法,
4.1、首先是构造方法,把需要的方法打包成一个Blob,里面有加载bundle的方法,有判断是不是dev(开发环境)的方法,有发送数据的方法,有接受数据的方法,接收数据的方法,在ReactExecutor.js里面。
然后新建一个工人,工人的onmessage(接受数据)方法里面会把接收到的消息放到消息队列中,自此构造方法结束
4.2、moduleConfig,里面是原生的模块(IManager、AndroidConstants、AsyncLocalStorage、ControllerInfo、History、Networking、LinkingManager、Location、Timing、VideoModule、AudioModule、WebSocketModule、ReactVRConstants、RCTExceptionsManager、RCTSourceCode、ExternalAssets、GlyphTextures)
4.3、setConstant 设置常数
4.4、exec 这个是发送bundle
4.5、call 执行方法,传递参数
4.6、invoke 执行方法,传递参数,传递是是viewtag id
4.5、flush 执行方法,传递参数
上面的这写方法都是工人发送出去的数据,发送出去以后,ReactNativeContext上下文中就会一直frame,这里面会把工人的消息队列里面的数据一条条取出来,然后只要有消息,就执行消息
5、发送消息,在react 一侧,在index.js的componentDidMount里面直接发送消息:
postMessage({type:'sceneLoadEnd'})//隐藏loading图
具体的消息传递就是,view调用frame方法,渲染每一帧的方法,也就是调用了上下文的frame方法,这个方法里面就是从工人的消息队列取数据,这个数据就是上面顶一个监听方法,监听的方法渠道对应的type,然后执行具体的方法,就是隐藏loading。
有啥不懂得,欢迎来询哦,QQ&微信:674668211