整体理解:
1.Java端和JS端各自维护着两个Map和一个消息队列。
一个Map维护着 提供给对方直接调用的方法,键值对<“方法关键字”,BridgeHandler>;在registerHandler时添加。
一个Map维护着 调用对方时自己提供的回调方法,键值对<Id, CallBackFuntion>; 在执行callhandler时,创建相应的Id, 并与CallbackFuction相关联存入HashMap。(在直接调用时,该ID被设置为Message的callBackId字段;在执行回调时,该ID被设置为Message的responseId字段。)
(注:java中map存的是对象,Js中Map存的是函数。额,对Js了解有限,知之不深。)
消息队列中存储着要发送给对方的消息。双方的要交互的信息都是封装成消息来进行交互的。
2.二者信息交互的方式就是获取对方的消息,并进行分发处理:
其中,
2.1 java向js传递消息,是通过loadUrl()来调用JS的
_dispatchMessageFromNative()
方法,然后进行消息分发处理逻辑:
如果是Java直接调用Js函数,根据 Message中函数关键字,从Map中获取对应的函数来执行。
如果是Java回调Js函数,根据 Message中回调函数的ID,从Map中获取对应的回调函数来执行。
2.2 Js向Java传递消息,是通过url重定向,触发WebviewClicent的
shouldOverrideUrlLoading()方法进行消息分发处理:
如果是JS直接调用Java方法,根据 Message中函数关键字,从Map中获取对应的BridgeHandler对象,执行其handler()方法。
如果是JS回调Java方法,根据 Message中回调函数的ID,从Map中获取对应的CallBackFunction对象,执行其onCallBack()方法。
一、JS调用Java过程:
#1.Java方的方法注册:
registerHandler(“【方法关键字】”, 实际逻辑执行BridgeHandler对象); HashMap把二者关联
BridgeHandler对象的
@Override
public void
handler(String callbackId
, String data
, CallBackFunction function) {
…...
}
#2.JS方的调用:
WebViewJavascriptBridge.JS中包含一些列相关的JS函数:
// Java方法名、传递的数据、回掉函数
function
callHandler(handlerName, data, responseCallback) {
console.log(arguments);
_doSend({
handlerName: handlerName,
data: data
}, responseCallback);
}
在_doSend函数中,会生成一个
callbackId
,用于标识回调函数。在Map中存储和关联。
所有数据:调用关键字、传递数据、回调函数Id值 都被封装到Message中。Message被放在消息队列中。
messagingIframe.src
值的修改应该类似于url重定向之类的吧,总之能触发WebviewClient的URL拦截方法shouldOverrideUrlLoading()方法。
而在约定中,封装的这个url字符串的含义,等同于说消息队列中有消息,快来取呀!
//sendMessage add message, 触发native处理 sendMessage
function
_doSend(message, responseCallback) {
if
(responseCallback) {
var
callbackId =
'cb_'
+ (uniqueId++) +
'_'
+
new
Date().getTime();
console.log(callbackId);
responseCallbacks[callbackId] = responseCallback;
message.callbackId = callbackId;
}
sendMessageQueue.push(message);
messagingIframe.src = CUSTOM_PROTOCOL_SCHEME +
'://'
+ QUEUE_HAS_MESSAGE;
}
shouldOverrideUrlLoading()中拦截并解析相应url,执行相应的判断逻辑分支,触发对应的逻辑链条:
0.创建一个回调对象,放到一个map中。该回调对象封装了JS消息的处理逻辑。
1.调用 能够取出JS消息队列中消息 的JS函数;
2.该JS函数,把消息队列中的消息数据封装后,以自定义的URL格式写在URL中。通过URL重定向,再次触发WebviewClient中的shouldOverrideUrlLoading()方法。
3.shouldOverrideUrlLoading()中拦截并解析相应URL,执行相应的逻辑分支:
从步骤0中的map取出相应回调对象,执行JS消息的处理,逻辑循环取出各个消息,依次做处理:
创建回调JS的CallBackFunction对象,它执行的相应逻辑是,把各个相关数据封装成Message: 数据体、回调函数的callbackId,调用JS相应函数来分发处理相应消息。
根据Message 要调用的 java方法名,从map中取出对应的BridgeHandler对象,调用其handler方法,传入各个之前已封装好的参数,至此JS真正开始调用开发者自定义的那部分逻辑。
当触发上面回调JS的CallBackFunction对象的逻辑,并按顺序触发到JS的消息分发逻辑时,JS会判断该消息是哪种类型:java直接调用、Java回调? 如果是Java回调操作,则从事先存储的map中按照callBackId取出对应的回调函数,并执行。
二、Java调用JS的过程
(有空再补)