作者:心恭弘=叶 恭弘
时刻:2019-03-25 10:18
道理概述
简介
JSBridge是Native代码与JS代码的通讯桥梁。如今的一种一致计划是:H5触发url scheme->Native捕捉url scheme->原生剖析,实行->原生挪用h5。以下图:
url scheme引见
上图中有提到url scheme这个观点,那这究竟是什么呢?
url scheme是一种类似于url的链接,是为了轻易app直接相互挪用设想的
- 详细为,能够用体系的OpenURI翻开一个类似于url的链接(可拼入参数),然后体系会举行推断,假如是体系的url scheme,则翻开体系运用,不然找看是不是有app注册这类scheme,翻开对应app
- 须要注重的是,这类scheme必需原生app注册后才会见效,如微信的scheme为(weixin://)
而本文JSBridge中的url scheme则是模仿上述的情势的一种体式格局
- 详细为,app不会注册对应的scheme,而是由前端页面经由历程某种体式格局触发scheme(如用iframe.src),然后Native用某种要领捕捉对应的url触发事宜,然后拿到当前的触发url,依据定义好的协定,剖析当前触发了那种要领,然后依据定义来实行等
- 注重,iOS10今后,urlscheme必需相符url范例,不然会报错
完成流程
基于上述的基础道理,如今最先设想一种JSBridge的完成
完成思绪
要完成JSBridge,我们能够举行关键步骤剖析
- 第一步:设想出一个Native与JS交互的全局桥对象
- 第二步:JS怎样挪用Native
- 第三步:Native怎样得知api被挪用
- 第四步:剖析url-参数和回调的花样
- 第五步:Native怎样挪用JS
- 第六步:H5中api要领的注册以及花样
以下图:
第一步:设想出一个Native与JS交互的全局桥对象
我们划定,JS和Native之间的通讯必需经由历程一个H5全局对象JSbridge来完成,该对象有以下特征
- 该对象名为”JSBridge”,是H5页面中全局对象window的一个属性
var JSBridge = window.JSBridge || (window.JSBridge = {});
该对象有以下要领
- registerHandler(String,Function) H5挪用,注册当地JS要领,注册后Native可经由历程JSBridge挪用。挪用后会将要领注册到当地变量messageHandlers 中 - callHandler(String,JSON,Function) H5挪用,挪用原生开放的api,挪用后现实上照样当地经由历程url scheme触发。挪用时会将回调id存放到当地变量responseCallbacks中 - _handleMessageFromNative(JSON) Native挪用,原生挪用H5页面注册的要领,或许关照H5页面实行回调要领
- 如图
第二步:JS怎样挪用Native
在第一步中,我们定义好了全局桥对象,能够我们是经由历程它的callHandler要领来挪用原生的,那末它内部阅历了一个怎样的历程呢?以下:
callHandler函数内部完成历程
在实行callHandler时,内部阅历了以下步骤:
- (1)推断是不是有回调函数,假如有,天生一个回调函数id,并将id和对应回调增加进入回调函数鸠合responseCallbacks中
- (2)经由历程特定的参数转换要领,将传入的数据,要领名一同,拼接成一个url scheme
//url scheme的花样如
//基础有效信息就是背面的callbackId,handlerName与data
//原生捕捉到这个scheme后会举行剖析
var uri = CUSTOM_PROTOCOL_SCHEME://API_Name:callbackId/handlerName?data
- (3)运用内部早就建立好的一个隐蔽iframe来触发scheme
//建立隐蔽iframe历程
var messagingIframe = document.createElement('iframe');
messagingIframe.style.display = 'none';
document.documentElement.appendChild(messagingIframe);
//触发scheme
messagingIframe.src = uri;
注重点:
注重,平常来说是能够经由历程window.location.href到达提议收集要求的效果的,但是有一个很严重的题目,就是假如我们一连屡次修正window.location.href的值,在Native层只能吸收到最后一次要求,前面的要求都会被疏忽掉。所以JS端提议收集要求的时刻,须要运用iframe,如许就能够防止这个题目。
第三步:Native怎样得知api被挪用
在上一步中,我们已胜利在H5页面中触发scheme,那末Native怎样捕捉scheme被触发呢?
依据体系差别,Android和iOS离别有本身的处置惩罚体式格局
Android捕捉url scheme
在Android中(WebViewClient里),经由历程shouldoverrideurlloading能够捕捉到url scheme的触发
public boolean shouldOverrideUrlLoading(WebView view, String url){
//读取到url后自行举行剖析处置惩罚
//假如返回false,则WebView处置惩罚链接url,假如返回true,代表WebView依据顺序来实行url
return true;
}
别的,Android中也能够不经由历程iframe.src来触发scheme,android中能够经由历程window.prompt(uri, “”);来触发scheme,然后Native中经由历程重写WebViewClient的onJsPrompt来猎取uri
iOS捕捉url scheme
iOS中,UIWebView有个特征:在UIWebView内提议的一切收集要求,都能够经由历程delegate函数在Native层获得关照。如许,我们能够在webview中捕捉url scheme的触发(道理是应用 shouldStartLoadWithRequest)
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *requestString = [[request URL] absoluteString];
//猎取利润url scheme后自行举行处置惩罚
return YES;
}
以后Native捕捉到了JS挪用的url scheme,接下来就该到下一步剖析url了
第四步:剖析url-参数和回调的花样
在前面的步骤中,Native已吸收到了JS挪用的要领,那末接下来,原生就应该根据定义好的数据花样来剖析数据了
url scheme的花样,前面已提到。Native吸收到Url后,能够根据这类花样将回调参数id、api名、参数提取出来,然后按以下步骤举行
- (1)依据api名,在当地找寻对应的api要领,而且纪录该要领实行完后的回调函数id
(2)依据提取出来的参数,依据定义好的参数举行转化
- 假如是JSON花样须要手动转换,假如是String花样直接能够运用
- (3)原生当地实行对应的api功用要领
(4)功用实行终了后,找到此次api挪用对应的回调函数id,然后连同须要通报的参数信息,组装成一个JSON花样的参数
- 回调的JSON花样为:{responseId:回调id,responseData:回调数据}
- responseId String型 H5页面中对应须要实行的回调函数的id,在H5中天生url scheme时就已发生
- responseData JSON型 Native须要通报给H5的回调数据,是一个JSON花样: {code:(整型,挪用是不是胜利,1胜利,0失利),result:详细须要通报的效果信息,能够为恣意范例,msg:一些别的信息,如挪用毛病时的毛病信息}
(5)经由历程JSBridge关照H5页面回调
- 参考 第五步Native怎样挪用JS
第五步:Native怎样挪用JS
到了这一步,就该Native经由历程JSBridge挪用H5的JS要领或许关照H5举行回调了,详细以下
//将回调信息传给H5
JSBridge._handleMessageFromNative(messageJSON);
如上,现实上是经由历程JSBridge的_handleMessageFromNative通报数据给H5,个中的messageJSON数据花样依据两种差别的范例,有所区别,以下
Native关照H5页面举行回调
数据花样为:上文中的回调的JSON花样
Native主动挪用H5要领
Native主动挪用H5要领时,数据花样是:{handlerName:api名,data:数据,callbackId:回调id}
- handlerName String型 须要挪用的,h5中开放的api的称号
- data JSON型 须要通报的数据,牢固为JSON花样(因为我们牢固H5中注册的要领吸收的第一个参数必需是JSON,第二个是回调函数)
注重,这一步中,假如Native挪用的api是h5没有注册的,h5页面上会有对应的毛病提醒。
别的,H5挪用Native时,Native处置惩罚终了后一定要实时关照H5举行回调,要不然这个回调函数不会自动烧毁,多了后会激发内存走漏。
第六步:H5中api要领的注册以及花样
前面有提到Native主动挪用H5中注册的api要领,那末h5中怎样注册供原生挪用的api要领呢?花样又是什么呢?以下
H5中注册供原生挪用的API
//注册一个测试函数
JSBridge.registerHandler('testH5Func',function(data,callback){
alert('测试函数吸收到数据:'+JSON.stringify(data));
callback&&callback('测试回传数据...');
});
如上述代码为注册一个供原生挪用的api
H5中注册的API花样注重
如上代码,注册的api参数是(data,callback)
个中第一个data即原生传过来的数据,第二个callback是内部封装过一次的,实行callback后会触发url scheme,关照原生猎取回调信息
思绪
大抵思绪就是
h5挪用Native的关键步骤举行拆分,由之前的直接通报url scheme变成通报一个一致的url scheme,然后Native主动猎取通报的参数
- 完美之前: H5挪用Native->将一切参数组装成为url scheme->原生捕捉scheme,举行剖析
- 完美今后: H5挪用Native->将一切参数存入当地数组->触发一个牢固的url scheme->原生捕捉scheme->原生经由历程JSBridge主动猎取参数->举行剖析
完成
这类完美后的流程和之前有所区别,以下
JSBridge对象图解
JSBridge完成完整流程
注重
因为此次完美的中心是:Native主动挪用JS函数,并猎取返回值。而在Android4.4之前,Android是没有这个功用的,所以并不完整适用于Android
所以平常会举行一个兼容处置惩罚,Android中采纳之前的scheme传法,iOS运用完美后的计划(也便于4.4提高后后续的完美)
完整的JSBridge
上述剖析了JSBridge的完成流程,那末现实项目中,我们就应该连系上述两种,针对Android和iOS的差别状况,一致出一种完整的计划,以下
完整挪用流程图
例子
基于上面的头脑,个人在github上保护了一个用于进修的项目(非转载内容):
https://github.com/yelloxing/…
不采纳url scheme体式格局
前面提到的JSBridge都是基于url scheme的,但实在假如不斟酌Android4.2以下,iOS7以下,实在也能够用另一套计划的,以下:
- Native挪用JS的要领稳定
- JS挪用Native是不再经由历程触发url scheme,而是采纳自带的交互,比方
- Android中,原生经由历程 addJavascriptInterface开放一个一致的api给JS挪用,然后将触发url scheme步骤变成挪用这个api,其他步骤稳定(相当于之前是url吸收参数,如今变成api函数吸收参数)
- iOS中,原生经由历程JavaScriptCore内里的要领来注册一个一致api,其他和Android中一样(这里就不须要主动猎取参数了,因为参数能够直接由这个函数一致吸收)