(转)iOS- JSBridge的道理

作者:心恭弘=叶 恭弘
时刻:2019-03-25 10:18

道理概述

简介

JSBridge是Native代码与JS代码的通讯桥梁。如今的一种一致计划是:H5触发url scheme->Native捕捉url scheme->原生剖析,实行->原生挪用h5。以下图:

《(转)iOS- JSBridge的道理》

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要领的注册以及花样

以下图:
《(转)iOS- JSBridge的道理》

第一步:设想出一个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页面实行回调要领
    
  • 如图

《(转)iOS- JSBridge的道理》

第二步: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对象图解

《(转)iOS- JSBridge的道理》

JSBridge完成完整流程

《(转)iOS- JSBridge的道理》

注重
因为此次完美的中心是:Native主动挪用JS函数,并猎取返回值。而在Android4.4之前,Android是没有这个功用的,所以并不完整适用于Android

所以平常会举行一个兼容处置惩罚,Android中采纳之前的scheme传法,iOS运用完美后的计划(也便于4.4提高后后续的完美)

完整的JSBridge

上述剖析了JSBridge的完成流程,那末现实项目中,我们就应该连系上述两种,针对Android和iOS的差别状况,一致出一种完整的计划,以下

完整挪用流程图

《(转)iOS- JSBridge的道理》

例子

基于上面的头脑,个人在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中一样(这里就不须要主动猎取参数了,因为参数能够直接由这个函数一致吸收)
    原文作者:心恭弘=叶 恭弘
    原文地址: https://segmentfault.com/a/1190000018641395
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞