当前位置: 首页 > news >正文

小榄网站佛山网页设计培训中心

小榄网站,佛山网页设计培训中心,大理建设工程信息网站,建设的比较好的档案馆网站前言 本文介绍quick hybrid框架的核心JSBridge的实现 由于在最新版本中#xff0c;已经没有考虑iOS7等低版本#xff0c;因此在选用方案时没有采用url scheme方式#xff0c;而是直接基于WKWebView实现 交互原理 具体H5和Native的交互原理可以参考前文的H5和Native交互原理 …前言 本文介绍quick hybrid框架的核心JSBridge的实现 由于在最新版本中已经没有考虑iOS7等低版本因此在选用方案时没有采用url scheme方式而是直接基于WKWebView实现 交互原理 具体H5和Native的交互原理可以参考前文的H5和Native交互原理 交互原理图如下 预计的最终效果 如果一步一步来分析最后再看效果可能会很枯燥甚至还有点化简为繁的样子。感觉直接看代码应该是最简单的奈何每次写成文章时都得加一大堆的描述 因此先来看看最终完成后应该是什么样的。 // 调用ui中alert的示例 callHandler({// 模块名本文中的API划分了模块module: ui,// 方法名name: alert,// 需要传递给native的请求参数data: {message: hello,},callback: function(res) {/*** 调用后的回调接收原生传递的回调数据* alert如果成功可以点击后再回调{// 1成功/0失败code: 1,message: 描述,// 数据data: {},}*/} }); 架构 从头开始实现一个JSBridge很容易两眼一抹黑无从下手。 因此我们需要先从大方向上把功能交互确定好然后再开始构建细节编码实现 功能分析与确认 根据核心架构规划需要实现的功能 H5桥接对象的设计JSBridge 短期回调池需自动回收长期回调池可多次使用调用Native方法的通道桥接对象上原生注册的接收方法接收Native调用的通道桥接对象上H5注册的接收方法H5可以注册主动给原生调用的方法原生桥接对象的设计 长期方法池每一个长期调用都会存储在回调池中可以多次使用短期立即执行每一个短期调用都是立即执行调用H5方法的通道桥接对象上H5注册的接收方法接收H5调用的通道桥接对象上原生注册的接收方法底层自动解析然后执行对应API回调对象底层基于调用H5的通道每次执行完毕后都通过回调对象回调给H5主动调用H5不同于回调对象只能被动响应这个可以主动调用H5中注册的方法API的设计 H5中的API供前端调用底层通过调用Native方法的通道然后将预处理后的参数发送给原生Native中的API真正的功能实现接下来就是JSBridge的实现 全局通信对象的确认 最重要的是先把H5和Native通信时的几个全局桥接对象确定 JSBridgeH5端的桥接对象对象中绑定了接收原生调用的方法_handleMessageFromNative以及内部有对回调函数等进行管理webkit.messageHandlers.WKWebViewJavascriptBridge.postMessageiOS端的桥接对象这个方法接收H5的调用promptAndroid端的桥接对象为了方便直接重写了WebChromeClient中的onJsPrompt// H5端的内部逻辑处理 window.JSBridge {...}// 接收原生的调用有回调以及主动调用两种 JSBridge._handleMessageFromNative function() {...} // H5主动调用原生 if (os.ios) {// ios采用window.webkit.messageHandlers.WKWebViewJavascriptBridge.postMessage(...); } else {window.top.prompt(...); } JSBridge对象的实现 H5就依靠这个对象与Native通信这里仅介绍核心的逻辑 JSBridge {// 本地注册的方法集合,原生只能主动调用本地注册的方法messageHandlers: {},// 短期回调函数集合在原生调用完对应的方法后会自动删除回收responseCallbacks: {},// 长期存在的回调集合可以多次调用responseCallbacksLongTerm: {},_handleMessageFromNative: function(messageJSON) {// 内部的处理**如果是回调函数如果是短期回调responseCallbacks中查询回调id并执行执行后自动销毁如果是短期回调responseCallbacksLongTerm中查询回调id并执行***如果是Native的主动调用去本地注册的方法池messageHandlers中搜索并执行*},callHandler: function(...) {// 底层分别调用Android或iOS的原生接收方法// 如果是短期回调会将回调添加到responseCallbacks中// 如果是长期回调会将回调添加到responseCallbacksLongTerm中// 省略若干逻辑...if (os.ios) {// ios采用window.webkit.messageHandlers.WKWebViewJavascriptBridge.postMessage(...);} else {window.top.prompt(...);}},registerHandler: function(handlerName, handler) {// H5在本地注册可供原生调用的方法},... }; Android中桥接对象的实现 Android中的核心就是JSBridge其余都是围绕这个来的以下是伪代码列举主要的逻辑 public class JSBridge {// 缓存所有的API模块注册时添加进去static exposedAPIModlues new HashMap();static register(String apiModelName, Class? extends IBridgeImpl clazz) {// 注册时会自动寻找所有的框架API模块然后添加到缓存exposedAPIModlues每一个模块中可以有若干API// 每一个模块都需要实现IBridgeImpl接口...}static callAPI(...) {// 首先会解析参数H5中传递的解析出调用了哪一个API传递了些什么解析结果包括如下// port:H5传递的回调id是responseCallbacks或responseCallbacksLongTerm中的key// moduleName:调用的API的模块名用来检索exposedAPIModlues中注册的模块// name:调用的API的方法名在对于找到的模块中去查找API// 其他:包括传递的参数等等// 然后会根据H5的回调端口号生成一个回调对象用来回调通知H5Callback callback new Callback(port);// 之后根据解析的参数寻找API方法// java.lang.reflect.Method;Method method searchMethodBy(moduleName, name);// 没有找到方法会回调对于错误信息// 否则执行对于的method传递解析出的参数// 并且在method内部执行完毕后主动回调给H5对于信息method.invoke(..., callback);} } callback类伪代码如下 public class Callback {apply(...) {// 先解析拼装参数然后将参数组装成javascript代码参数中包含Callback对于的port值回调id...String js javascript:JSBridge._handleMessageFromNative(对于的json参数);callJS(js);}callHandler(...) {// 主动调用H5封装的参数中不再是回调id而是handleName...callJS(js);}callJS(js) {// 底层通过loadUrl执行...webviewContext.loadUrl(js);} } IBridgeImpl接口是空的只是一个抽象定义以下以某个实现这个接口的API为例 // 为了清晰以ui.alert为例 public class xxxApi implements IBridgeImpl {// 定义一个注册的模块别名方便查找譬如uistatic RegisterName ui;// 模块中的某个API譬如alertpublic static void alert(..., Callback callback) {// 接下来就是在这个API中实现对于的逻辑...// 最后通过触发callback通知H5即可callback.apply(...);} } 最后可以看到在webview中重新了WebChromeClient的onJsPrompt来接收H5的调用 并且在webview加载时就会调用JSBridge的register public class XXXWebChromeClient extends WebChromeClient {Overridepublic boolean onJsPrompt(..., JsPromptResult result) {// 内部触发JSBridge.callJavaresult.confirm(JSBridge.callJava(...));return true;} } 以上几个就是Andorid中JSBridge核心实现其他的如长期回调短期回调细节实现等优化不是核心逻辑就列举详情可以参考最后的源码 iOS中桥接对象的实现 这里仍然是OC实现的主要参考的marcuswestin/WebViewJavascriptBridge实现 核心仍然是WKWebViewJavascriptBridge其余一切都是通过它来分发代理 implementation WKWebViewJavascriptBridge {// 内部基于一个WebViewJavascriptBridgeBase基类基类中定义交互方法WebViewJavascriptBridgeBase *_base; } /*** API*/ - (void)callHandler:(NSString *)handlerName data:(id)data {// 主动调用H5的方法// 底层调用_base的sendData发送数据给H5 }- (void)registerModuleFrameAPI {// 注册模块API模块用到了别名代理[self registerHandlersWithClassName:UIApi moduleName:ui];// 其中registerHandlersWithClassName就是将模块示例化注册到全局中的作用不赘述 }- (void)excuteMessage:(NSString *)message {// 内部执行API的实现这里会解析API解析出来的数据如// module.name,port(callbackid)等...// 然后底层调用_base的excuteMsg它内部会根据注册的API找到相对应的然后执行原生功能最后通过回调通知H5 }#pragma mark - WKScriptMessageHandler其实就是一个遵循的协议它能让网页通过JS把消息发送给OC - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {// 监听到对于API调用时底层会调用excuteMessageif ([message.name isEqualToString:WKWebViewJavascriptBridge]) {[self excuteMessage:message.body];} } 然后看看它基类WebViewJavascriptBridgeBase的实现 implementation WebViewJavascriptBridgeBase- (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName {// 底层将接收到的数据组装成js代码执行...NSString* javascriptCommand [NSString stringWithFormat:JSBridge._handleMessageFromNative(%);, messageJSON];[_webView evaluateJavaScript:javascriptCommand completionHandler:nil]; }- (void)excuteMsg:(NSString *)messageQueueString moduleName:(NSString *)moduleName {// 底层根据对于的模块API名找到注册的handler...// 然后创建一个回调对象WVJBResponseCallback responseCallback (通过sendData通知H5回调数据);// 然后执行这个handlerhandler(message[data], responseCallback); } 接下来是API的定义 定义API模块之前需要先了解RegisterBaseClass所有模块必须实现的基类定义了如何注册 implementation RegisterBaseClass #pragma mark - 注册api的统一方法 - (void)registerHandlers {// 子类重写改方法实现自定义API注册 }#pragma mark - handler存取 - (void)registerHandlerName:(NSString *)handleNamehandler:(WVJBHandler)handler {// 注册某个模块下的某个API }- (WVJBHandler)handler:(NSString *)handlerName {// 通过名称获取对应的API } 要定义一个API模块则需继承RegisterBaseClass然后重写registerHandlers为了清晰以ui.alert为例 implementation UIApi - (void)registerHandlers {[self registerHandlerName:alert handler:^(id data, WVJBResponseCallback responseCallback) {// 同样在接收到数据并处理后通过responseCallback通知H5...responseCallback(...);} } 在webview加载时就会调用WKWebViewJavascriptBridge的registerModuleFrameAPI对于模块名ui与别名UIApi可以在注册时看到它们之间是有一一对应关系的 然后在webview创建时会进行监听userContentController WKWebViewConfiguration * webConfig [[WKWebViewConfiguration alloc] init]; WKUserContentController * userContentVC [[WKUserContentController alloc] init]; webConfig.userContentController userContentVC; WKWebView * wk [[WKWebView alloc] initWithFrame: CGRectZero configuration: webConfig];self.wv wk; ...// 代理 self.bridge [WKWebViewJavascriptBridge bridgeForWebView: self.wv]; [self.bridge setWebViewDelegate: self];// 添加供js调用oc的桥梁。这里的name对应WKScriptMessage中的name多数情况下我们认为它就是方法名。 [self.wv.configuration.userContentController addScriptMessageHandler: self.bridge name: WKWebViewJavascriptBridge]; 同样iOS中的长期回调等其它一些非核心内容也暂时隐藏了 API的设计 按照上述的实现可以构建出一个完整的JSBridge交互流程H5和Native的交互已经通了 接下来就是设计API真正给外界调用 准确的来说API的设计已经脱离了JSBridge交互内容属于混合框架框架应用层次因此后续会有单独的章节介绍quick hybrid中的API API如何实现可以参考上文中Android的继承IBridgeImpl法以及iOS的继承RegisterBaseClass然后重写registerHandlers 至于该规划些什么API这与实际的需求有关不过一般情况下像ui.alert等等一般都是必须的 更多详情请待后续章节 结束语 最后再来一张图巩固下把 至此整个JSBridge交互就已经完成了 其实在总结文章时考虑过很多种形式发现 如果是全文字描述十分枯燥很难坚持读下来 如果是各种原理都用绘图描述发现会化简为繁硬生生把难度提高了几个level 所以最终采用的是伪代码半伪半真展示形式剔除一些无效信息提取关键而且还不和最终的代码冲突 虽然说这整套流程都没有特别难的地方涉及的知识点都不是特别深。但是却包含了前端AndroidiOS三个领域。 因此如果要将整套工作做的比较好的化最好还是有分工的好比较一个人的精力有限真正专精多个领域的人还是比较少的 而且后续各个优化的内容也不少API优化等等... 返回根目录 【quickhybrid】如何实现一个Hybrid框架源码 github上这个框架的实现 quickhybrid/quickhybrid 附录 参考资料 marcuswestin/WebViewJavascriptBridge转载于:https://www.cnblogs.com/dailc/p/8098597.html
http://www.yutouwan.com/news/264406/

相关文章:

  • 网站建设优化推广安徽招标
  • 永久免费素材网站深圳网页制作哪家好
  • 网站建设地位wordpress 小工具 插件
  • 小门户网站模板阿里云 企业网站选哪种
  • 网站管理包括百度联盟怎么做网站
  • 网站后台英文专业简历制作平台
  • 阿里云做网站麻烦吗网站国际推广
  • 网站制作将栏目分类百姓网地址怎么创建
  • 乌市正规网站建设学网站开发好吗
  • 网站建设管理员工工资多少钱网盘做扩大网站服务器
  • 网站dns设置线上销售培训班课程
  • 模仿网站 素材哪里来企业宣传册设计与制作
  • 制作网站源码中企动力科技股份有限公司西安分公司
  • wordpress小工具用不徐州seo外包
  • 怎样建设网站公司网络软文营销案例3篇
  • 做特卖的网站爱库存WordPress连接云储存
  • 网站推广主要方法网站需要去工信部做备案
  • 唐山做网站优化如何搭建app开发平台
  • 网站建设需要些什么东西安卓优化大师app下载安装
  • 网站建设硬件需求宁波网站建设团队
  • 如何用ps做网站首页山东省住房和城乡建设厅注册中心网站
  • 青岛网站设计建设施工企业的主要负责人是本单位的
  • 如何做免费网站推广wordpress get_option array
  • 安徽元鼎建设公司网站万网官网登录入口
  • 中国设计最好的网站义乌婚介网站建设
  • 网站建设的数据导入导出做网站后台系统的规范
  • 二级院系网站建设长沙网站开发招聘
  • 怎样选择网站服务器网页制作网站开发流程
  • 松原网站建设哪家好怎么区分模板网站和定制网站
  • 企业网站建设和管理漯河网站建设zrgu