1.使用方法
1.1,java调用js指定方法,并有回调:
1 | //java端的代码 |
1 | //H5端的代码 |
java调用callHandler()的方法,必须要在H5中registerHandler(),而且方法名一样才能匹配到,
所以执行上可以看成 java—>js—>java。
1.2,js调用java
1,js发送消息给native端,并有回调
因为没有指定要处理的方法,则由java端的DefaultHandler拦截处理
1 | //js代码 |
1 | //java代码 |
js调用window.WebViewJavascriptBridge.send()的方法,会被java的DefaultHandler拦截
所以执行上可以看成 js—>java—>js。
2,js调用java指定方法,并有回调
1 | //js代码 |
1 | //java代码 |
2.执行流程分析
2.1,java调用指定方法,并有回调。
在java代码中,首先找到方法的入口,callHandler()。
1 | webView.callHandler("functionInJs", params, new CallBackFunction() { |
进入callHandler()方法,调用了doSend()方法。
1 | public void callHandler(String handlerName, String data, CallBackFunction callBack) { |
看doSend()代码
1 | /** |
这里组装Message对象来保存调用方法的信息,假如存入了回调函数responseCallback ,则生成一个callbackStr 保存到本地的responseCallbacks中,继续进入queueMessage()方法
1 | private void queueMessage(Message m) { |
假如native调用js代码,则startupMessage为null,所以进入到dispatchMessage()方法中
1 | void dispatchMessage(Message m) { |
这段代码就是native调用js代码的关键,方法中先从message对象中解析json数据将信息解析,拼接出类似
1 | javascript:WebViewJavascriptBridge._handleMessageFromNative('{\"callbackId\":\"JAVA_CB_1_877\",\"data\":\"{\\\"location\\\":{\\\"address\\\":\\\"SDU\\\"},\\\"name\\\":\\\"大头鬼\\\"}\",\"handlerName\":\"functionInJs\"} |
的代码,再通过
1 | if (Thread.currentThread() == Looper.getMainLooper().getThread()) { |
在主线程中webView.loadUrl(),所以其实java调用js的核心还是webView.loadUrl()这个方法,但是JsBridge库对其进行了封装,这样java就不能调用js中的任意代码(本来webView.loadUrl()这个方法只要传入拼接对的js代码,就能调用该js代码)。
追踪到js的WebViewJavascriptBridge._handleMessageFromNative代码
1 | function _handleMessageFromNative(messageJSON) { |
这里还没搞懂receiveMessageQueue 的作用是什么,只知道调用了_dispatchMessageFromNative()方法,所以继续进入方法
1 | //按照messageJson进行事件的调用,假如有callback,则调用完之后callback |
这段代码中,因为是java主动调用js,所以message.responseId为null,直接走else,先组装回调函数responseCallBack()
1 | if (message.callbackId) { |
接着根据handler = messageHandlers[message.handlerName];拿到handler
1 | //查找指定handler |
最后就是调用方法,追踪到注册的方法
1 | connectWebViewJavascriptBridge(function(bridge) { |
最后调用了responseCallback(responseData),responseCallback()在上面已经组装成功,就是调用了_doSend()这个方法
1 | //sendMessage add message, 触发native处理 sendMessage |
这里涉及到一些前端的知识,利用iframe.src的变化,触发了BridgeWebViewClient的shouldOverrideUrlLoading将数据返回到native端,这样就实现了js回调到native了。
所以总体上流程是:

Paste_Image.png
3,js调用java指定方法,并有回调
找到js代码的入口,window.WebViewJavascriptBridge.callHandler(…)
1 | //function的responseData是回调的值 |
进入callHandler()方法,也是调用了_doSend()方法,将数据传递到native
1 | function callHandler(handlerName, data, responseCallback) { |
与上面js调用java流程中的_doSend()一样,通过改变iframe.src触发native的shouldOverrideUrlLoading()方法
1 |
|
接着走的是webView.flushMessageQueue()这个方法
1 | void flushMessageQueue() { |
这个方法是在BridgeWebView中定义的,做的是在主线程中调用loadUrl(javascript:WebViewJavascriptBridge._fetchQueue(), new CallBackFunction());这个方法。
所以,追踪到js中的_fetchQueue()中
1 | // 提供给native调用,该函数作用:获取sendMessageQueue返回给native,由于android不能直接获取返回的内容,所以使用url shouldOverrideUrlLoading 的方式返回内容 |
这里将js传递的参数拼接入Url中,传递到native,而相应的shouldOverrideUrlLoading 中调用handlerReturnData()这个方法
1 | /** |
这里就是调用native本地方法
1 | if (f != null) { |
所以总体上流程是

Paste_Image.png
留意整个流程,js的第一次_doSend()只不过是通知native调用javascript:WebViewJavascriptBridge._fetchQueue();来取消息,包括要调用的方法,参数,回调的id。所以其实真正调用native方法的是js层的_fetchQueue()。
作者:EdisonJQ
链接:https://www.jianshu.com/p/b740e640a41c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文链接: http://www.ionluo.cn/blog/posts/ffcbbe3b.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
