10

本人最近在研究hybrid的实现原理且读了一些源码 仅限前端js的 所以非前端或非hybrid模式的童鞋可以绕过~

首先简介下url scheme

手机APP都有一个沙盒,可以注册自己的URL Scheme。我们可以通过系统的OpenURL来打开该app,并可以传递一些参数。例如:
CtripWireless://打开携程App
weixin:// 打开微信

目前大部分hybrid设计都是沿用JSBridge的,在不同的平台通过不同的native层实现,在各自平台下完成编译。

什么是JSBridge?

顾名思义,JSBridge就是定义Native和JS的通信,Native只通过一个固定的桥对象调用JS,JS也只通过固定的桥对象调用Native,基本原理是:

H5->通过某种方式触发一个url->Native捕获到url,进行分析->原生做处理->Native调用H5的JSBridge对象传递回调。

图片描述

实现思路

首先需要在全局对象Global下新建一个Bridge对象,实现以下3个方法:

  1. jsCallNative(method, param, callback): h5主动调用native
  2. nativeCallback(param): native主动调用h5
  3. listenToNativeEmitMessage(msg, callback): h5注册函数供Native调用

jsCallNative

  1. 判断是否有回调函数callback,有就生成一个sequenceId,并将id和对应callback添加进入回调函数集合responseCallbacks中

(Reason:Js函数不能跨语言传递,Native无法识别,但字符串/数字可以。使用自增长的sequenceId代替callback函数,传递给Native,Bridge内部记录一个全局对象responseCallbacks,记录sequenceId和callback函数之间的mapping关系。传递给Native的是sequenceId,Native处理完成之后,返回的时候,都带上对应的sequenceId。Bridge收到回调之后,根据sequenceId,取出对应的callback函数,然后调用。)

  1. 将传参拼接转换成url,如schema://forward?param={foo:1}&sequenceId=1
  2. 使用一个隐藏的iframe来触发scheme

    图片描述

  3. Native监听url变化,由于这里是Native的实现就不赘述了,值得注意的是这里如果有callback回调,需要带上参数sequenceId,与主动调用h5的参数是有区别的

图片描述

nativeCallback

这里承接上个方法最后提到的Native主动调用h5
图片描述

附上代码

图片描述

可以看到,如果存在msg也就是function名,直接调用msgListenerList[msg](data);不然就是执行回调responseCallbacks[sequenceId](data),如果Native调用的api是h5没有注册的,h5页面上会有对应的错误提示'Error NativeCallback: blabla'

这个msgListenerList是哪来的呢?看最后个方法

listenToNativeEmitMessage

附上代码

listenToNativeEmitMessage: function(msg, callback) {
  msg && callback && msgListenerList.push({emitMessageName: callback});
}

例如Native监听到网络状态变更,大家经常会遇到,在wifi看视频时突然切成4g了需要提醒用户

Bridge.listenToNativeEmitMessage('networkStateChange', function(data){
  console.log('network type: ' + data.networkType);
});

结语

大概的流程就这些,自己也是初学者,查了很多资料,若有错误希望指正~
附上我的代码: webview-js-bridge


小皇帝James
600 声望7 粉丝

IT吴彦祖