开源代码分析之Android/iOS Hybrid JSBridge框架

Hybrid开发是如今的主流形式,对于业务快速迭代的公司尤为重要。曾将在鞋厂接触了不少关于Hybrid的理念,在这里分享一些Hybrid框架思想。前端

Hybrid框架包括Native与H5的通讯,WebView的管理等,这里主要介绍通讯。java

文章主要分为两个部分,第一部分介绍Hybrid与H5通讯的几种方式,第二部分分析了开源框架的具体作法。git

第一部分 Hybrid与H5通讯github

Hybrid与H5通讯实现方式有不少种,有基于url拦截的,也有基于prompt拦截的。web

最后分析的这个框架和PhoneGap同样采用prompt拦截,但内部处理机制没有PhoneGap复杂,暂时对PhoneGap不是彻底了解,就不装B了。框架

H5与Native通讯,如今采用最多的方式是依赖中间过渡的WebView,其余的不了解。异步

基于对Hybrid的了解,就分H5调用Native和Native通知H5。下面来细说这两点。函数

1.H5调用Nativeurl

这种方式主要是须要Native宿主环境经过WebView来提供一些H5调用的接口方法。spa

若是采用url拦截的,也就是经过一个隐藏iframe或者修改location发起请求,好比bridge://service/method?params&callback,能够在webview加载时获取到该url,并针对url信息分析对应到Native中的某个service类的某个method方法。

若是采用prompt拦截的,好比prompt(service,method,params,callback),原理与url方式差很少,不过是在H5发起prompt请求,webview截获到这个prompt中的参数,调用Native中对应的某个service类的某个method方法。

这两种方式通常会与一个Bridge.js配合,Bridge.js封装了bridge://service/method?params&callback的构造,或prompt(service,method,params,callback)的请求,提供H5良好的访问接口。

当H5端调用某个方法时,将对应的参数和回调封装成url或prompt的形式,而后请求webview,webview截获url或prompt,请求本地服务获取数据后,经过注册在window对象上的callback将请求结果返回给H5。

这两种方式的开源库可参考:jsbridge-to-cocoa(url+bridge.js)   safe-java-js-webview-bridge(prompt)

针对这两种基本方式可扩展,好比某所是直接采用了url+bridge这种方式,而鞋厂则针对性的作出些调整(后面针对性的介绍),还有后面介绍的safe-java-js-webview-bridge则与PhoneGap相似,消除了H5对Bridge.js的可见性,经过反射Native提供的service自动构造Bridge.js并注入到WebView中。

至于上面两种方式及其扩展的好坏之分,主要看设计上如何使H5调用变得简单则好,尽可能下降Native与H5的耦合,分清构造Bridge.js的职责。

2.Native通知H5

这种方式主要是H5将某些监听事件(如webview下拉刷新、native推送)绑定到window上,当Native须要调用H5时,能够经过webview中注册的这些事件回调通知H5。

Native通知H5的方式比H5调用Native来的简单,不过在项目中如何将两者结合起来,提供统一的调用接口则须要良好的设计。

若是须要完成H5与Native的相互访问,基本上采用上面两种方法便可完成,但若是要封装的对H5调用接口友好,则须要在设计上下功夫,这就是仁者见仁智者见智的事情。

后续会分别补充某所和鞋厂各自对Bridge.js的封装思想。//TODO

第二部分 开源框架分析

1.iOS开源框架 jsbridge-to-cocoa

先来看看jsbridge-to-cocoa的源码结构,由于不存在太多的设计思想,仅仅是上述方式的一个实现过程。

采用url拦截的方式实现H5调用Native,但调用后没有回调的过程,并且还未实现Native通知H5的过程。(可能理解有误差,大神勿喷)

下面说说这个框架的基本思想,Bridge.js中包含了供H5和Native使用的方法,分两步:

1. H5经过调用AddObject添加请求的参数和回调,经过SendObject封装的url来触发webview拦截;

2. Native中的webview拦截后,会分析url中的请求参数,调用本地服务,完成本地功能后会调用Bridge提供的接口,调用H5的回调

下面直接看看时序图,也比较易于理解。

注:描述过程和截图中都含有红色部分,是针对该框架的弱点提供的补充,便可保证H5访问Native后能回调H5的过程。

2.Android开源框架 safe-java-js-webview-bridge

抽空看了了下safe-java-js-webview-bridge的源码,整理了一份类之间的调用关系图。

值得推荐的是这个库屏蔽了H5对Bridge.js的可见性,并且Bridge.js是经过对Native中对外公开的类进行反射生成的,提升了复用性。

不过也有其缺点,Native提供给H5的方法都封装在一个Bridge.js中,若是Native须要暴露给H5的功能模块增多时,且须要按模块进行细分时,Bridge.js则显得有点模糊。

这个问题只须要对其原理熟悉,改形成支持多模块的成本也不大。后续补充源码链接,还在改造中。//TODO

注:这个库中Bridge.js这个文件名是不存在的,可自行指定,这里为了方便理解,因此采用Bridge.js。

下面说说开源库safe-java-js-webview-bridge的基本思路,分三步:

1.在native端编写调用本地功能的class(如HostJsScope.java),在初始化WebviewChromeClient时根据该class(在JsCallJava构造函数中)反射动态生成js代码;

2.将动态生成的js代码经过webview.loadUrl触发的onProgressChanged注入到webview中,供前端可调用;

3.在前端调用HostJsScope对应的接口,出发webview的onPrompt事件,进而调用本地HostJsScope方法,若是是同步且有返回值,经过prompt返回值返回,若是是异步,则反射调用JsCallback将数据返回前端。

先上图,后面逐步分析调用关系。(因为对UML时序图不甚了解,原谅图中的错误)

根据截图能够清晰的看到三个步骤的调用过程,若是有兴趣的能够拿源码对比该截图进行分析。

经过对以上两个开源框架的分析,能够理解H5调用Native并回调H5的通讯过程,但两者都为对Native通知H5的通讯实现,不过这部分实现也比较简单。原理上面也解释过了,经过截图来描述下。

Hybrid框架中H5与Native相互通讯的过程基本如此,不过不少原理细节未作过多描述,若是兴趣的同窗能够留言一块儿讨论。

相关文章
相关标签/搜索