写在前面的话:背景介绍:Ios Android Hybrid app 与 Js Bridge ,源码Github
一、项目模块主要介绍:
1. Bridge包括两模块:Javascript的bridge和Native的bridge,处理流程上基本上一致。
2. Bridge Web与Native通信流程:
3. Bridge Native与Web通信流程:
4. Bridge 的数据结构:
(1)消息体的字段,有两种消息体,一种是发送消息,一种是回复消息
callbackId; //字符串,若发送消息需要回调函数,则标识该字段,表明该消息需要接收方的回复
responseId; //字符串,在回复消息中标识该字段,且值与发送方发送消息时的callbackId值一致,也就是使用responseId、callbackId来唯一标识消息一来一回
responseData; //回复消息的内容,用于回复消息
data; //发送消息体的内容
handlerName; //发送消息体指定需要被处理的函数名,存放在接收方
(2)主要数据结构(在Js bridge和Native bridge端命名会有不同)
messageHandlers;//字典类型,或者Java开发者来说Map类型,key为handlerName,Value就是handlerName对应的处理函数
responseCallbacks;//字典类型,或者Java开发者来说Map类型,key为唯一标示,Value就是回调函数
uniqueId;//字符串或者整型,看具体实现,为了唯一标示消息体,在callbackId和resposneId中使用
sendMessageQueue;//数组,存放消息列表
5. Bridge 的处理message的流程:
二、项目代码主要介绍:
1. Javascript Bridge 源码(可见):
(1)Javascript触发Native反向调用方法如下,在上一篇中一1(1)说明为什么要这样做的原因。
//创建一个不可见的iframe,便可通过改变iframe,src来让Native反向调用Js端
function _createQueueReadyIframe(doc) {
messagingIframe = doc.createElement('iframe')
messagingIframe.style.display = 'none'
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
doc.documentElement.appendChild(messagingIframe)
}
(2)Javascript 处理Native发送过来的message源码如下
//提供给native使用,
function _dispatchMessageFromObjC(messageJSON) {
setTimeout(function _timeoutDispatchMessageFromObjC() {
var message = JSON.parse(messageJSON)
var messageHandler
//如果是回复类型消息,执行回调函数,并删除本地的对应的字典
if (message.responseId) {
var responseCallback = responseCallbacks[message.responseId]
if (!responseCallback) { return; }
responseCallback(message.responseData)
delete responseCallbacks[message.responseId]
} else {
var responseCallback
//如果是发送类型消息,并且发送有指定callbackId,说明是需要回复的,创建回复的函数
if (message.callbackId) {
var callbackResponseId = message.callbackId
responseCallback = function(responseData) {
_doSend({ responseId:callbackResponseId, responseData:responseData })
}
}
// js端默认的handler处理函数,表示如果native没有指定js端需要处理的handler函数时,则使用默认函数处理
var handler = WebViewJavascriptBridge._messageHandler
if (message.handlerName) {
handler = messageHandlers[message.handlerName]
}
//确定了指定handler,执行该handler
try {
handler(message.data, responseCallback)
} catch(exception) {
if (typeof console != 'undefined') {
console.log("WebViewJavascriptBridge: WARNING: javascript handler threw.", message, exception)
}
}
}
})
}
(3)Javascript是怎么发送消息到Native端的:
function _doSend(message, responseCallback) {
//如果有回调函数,则需要接收方回复消息,所以在消息体中赋值callbackId字段
if (responseCallback) {
var callbackId = 'cb_'+(uniqueId++)+'_'+new Date().getTime()
responseCallbacks[callbackId] = responseCallback
message['callbackId'] = callbackId
}
//加入消息队列
sendMessageQueue.push(message)
//触发Native拦截URL访问,也就达到了Native反向调用的目的
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
}
Javascript 端大概流程如上,Java端的Birdge流程也基本一致,只是编码语言不同和少量的细节问题不一致而已。