文档章节

JsBridge原理分析

Kingguary
 Kingguary
发布于 06/21 21:24
字数 1231
阅读 27
收藏 0

看了这个Github代码 https://github.com/lzyzsd/JsBridge,想起N年前比较火的Hybrid方案,想看看现在跨平台调用实现有什么新的实现方式。代码看下来之后发现确实有点独特之处,这里先把核心的思想抛出,然后在细化Native (Java)如何调JS以及JS如何调Native (Java)。

Native与JS相互调用使用的最核心的思路是:

1、Native通过WebView的loadUrl调用JS的code;

2、JS通过设置URL跳转触发WebViewClient的shouldOverrideUrlLoading通知Native有数据发生;

当然这只是核心思路,实际上还涉及到一些细节,其中比较重要的就是scheme的设计,双方都是通过这个scheme来约定方法和返回数据。可以参考BridgeUtils的YY_RETURN_DATA和YY_FETCH_QUEUE。当然还有方法名的约定;以及交换数据格式的约定(JSON)。

一、Native(Java)调JS

在Native调JS之前,需要现在JS中注册handler,也就是方法名与方法体, 参考Github README:

WebViewJavascriptBridge.registerHandler("functionInJs", function(data, responseCallback) {
        document.getElementById("show").innerHTML = ("data from Java: = " + data);
        var responseData = "Javascript Says Right back aka!";
        responseCallback(responseData);
    });

Native调用JS

webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() {
        @Override
        public void onCallBack(String data) {

        }
    });

需要传递之前约定的方法名,方法参数(json格式)以及一个JS执行结果返回的callbackFunction。

1、JS注册自己对外开放的接口,用于被Native调用;

2、外部调用BridgeWebView的callHanlder方法调用js接口,传递的参数为约定的方法名,json格式的参数以及一个callback,这个callback用于接收js接口返回的结果;

3、callHandler调用内部的doSend方法,doSend方法中构造一个message,这个message中包含方法名,参数json内容以及一个新构造的callbackId,这个id还用于接收js返回结果的callback的key,保存到map中用于后续查找对应的callback;然后会调用queueMessage进行分发;

4、queueMessage主要是调用dispatchMessage进行处理;

5、dispatchMessage中构造一个url用于进行js调用,这个url是“WebViewJavascriptBridge._handleMessageFromNative('message的json格式');”,

6、通过loadUrl触发js的接口被调用;

7、触发JsBridge中的_handleMessageFromNative被调用;

8、调用_dispatchMessageFromNative进行message消息的处理,

9、_dispatchMessageFromNative中,根据message的json,找到handler name并找到1中注册的handler,然后调用handler处理message中包含的data;在handler执行之前,构造了一个responseCallback,这个responseCallback在handler执行之后会被执行,

_doSend({
    responseId: callbackResponseId,
    responseData: responseData
});

10、_doSend中,这个json内容被放进一个queue中留作后用(主要是用于后续被Native请求得到),暂时不会直接返回,这个responseId就是之前传递过来的message中的callbackId;

var callbackResponseId = message.callbackId;

11、通过重定向url,触发BridgeWebViewClient的shouldOverrideUrlLoading;

12、在shouldOverrideUrlLoading中,会根据url的前缀判断调用webview中的哪个方法,这里调用的是flushMessageQueue;

13、flushMessageQueue中做的事情比较绕圈子,它首先构造了一个新的responseCallback,在这个responseCallback中封装了针对之前注册的callback的调用,之后,这个responseCallback作为方法‘return’的value存进map中,用于后续handlerReturnData中被处理;

14、通过loadUrl(‘WebViewJavascriptBridge._fetchQueue();’)触发JsBridge的_fetchQueue;

this.loadUrl(jsUrl);
      // 添加至 Map<String, CallBackFunction>
responseCallbacks.put(BridgeUtil.parseFunctionName(jsUrl), returnCallback);

这里jsUrl就是‘WebViewJavascriptBridge._fetchQueue();’

15、在jsBridge中的_fetchQueue函数中,把10中保存的queue中的json数据转换成json string,作为url的一部分进行跳转

function _fetchQueue() {
    var messageQueueString = JSON.stringify(sendMessageQueue);
    sendMessageQueue = [];
    //android can't read directly the return data, so we can reload iframe src to communicate with java
    bizMessagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://return/_fetchQueue/' + encodeURIComponent(messageQueueString);
}

这会导致BridgeWebViewClient的shouldOverrideUrlLoading被触发;

16、在BridgeWebViewClient的shouldOverrideUrlLoading中,这回根据url前缀,判断需要调用BridgeWebView的

webView.handlerReturnData(url);

17、在BridgeWebView的handlerReturnData中,

void handlerReturnData(String url) {
   String functionName = BridgeUtil.getFunctionFromReturnUrl(url);
   CallBackFunction f = responseCallbacks.get(functionName);
   String data = BridgeUtil.getDataFromReturnUrl(url);
   if (f != null) {
      f.onCallBack(data);
      responseCallbacks.remove(functionName);
      return;
   }
}

根据url找到对应的方法就是13中的‘return’以及它对应的callbackFunction,也是13中对callbackId对应的callback进行封装的callback,然后提取出15中的json data,回调callback。在onCallBack中,会找到json中的callbackId以及js执行的结果data,然后用callbackid对应的callback调用data完成js执行结果的处理。

至此,从Native调用JS以及处理JS调用返回内容的流程完毕。至于JS调用Native的流程跟这个类似,可以根据源码进行还原。总之还是开头总结的:

Native与JS相互调用使用的最核心的思路是:

1、Native通过WebView的loadUrl调用JS的code;

2、JS通过设置URL跳转触发WebViewClient的shouldOverrideUrlLoading通知Native有数据发生;

© 著作权归作者所有

共有 人打赏支持
Kingguary
粉丝 11
博文 71
码字总数 21482
作品 0
海淀
私信 提问
【quickhybrid】JSBridge的实现

前言 本文介绍框架的核心的实现 由于在最新版本中,已经没有考虑等低版本,因此在选用方案时没有采用方式,而是直接基于实现 交互原理 具体H5和Native的交互原理可以参考前文的 交互原理图如...

dailc
07/01
0
0
Android WebView 全面干货指南

前言 总结 Android WebView 常用的相关知识点,令包含以下干货内容分析:Js注入漏洞、WebView 遇到的坑、JsBridge 原理以及框架使用(JsBridge,DSBridge-Android)、缓存机制应用、性能优化、腾...

無名小子的杂货铺
2017/10/30
0
0
CC框架实践(3): 让jsBridge更优雅

前言 CC框架下如何让我们的jsBridge更加优雅? jsBridge是作为js和java之间通信的桥梁,本身它的职责只是完成通信。 本文不是介绍js与java通信过程的实现,你可以使用第三方库(如:JsBridg...

lucky_billy
06/20
0
0
Android JSBridge的原理与实现

原文出处: 安卓弟(@安卓弟) 在Android中,JSBridge已经不是什么新鲜的事物了,各家的实现方式也略有差异。大多数人都知道WebView存在一个漏洞,见WebView中接口隐患与手机挂马利用,虽然该...

刘星石
2016/03/07
277
0
【腾讯bugly干货分享】解耦---Hybrid H5跨平台性思考

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1275&extra=page%3D1 跨平台,是H5最重要的能力之一。而 Hybrid...

腾讯Bugly
2016/07/04
78
1

没有更多内容

加载失败,请刷新页面

加载更多

用POLARDB构建客到智能餐饮系统实践

摘要: 在新零售成为大趋势的今天,餐饮行业也加入到这一浪潮之中。智能餐饮系统将帮助餐饮行业从多个维度提升自己的运营能力和收益,而打造智能餐饮系统SaaS化能力也成为了目前的一个热点。...

阿里云官方博客
25分钟前
1
0
aws S3 util demo

package com.example.demo;import com.amazonaws.AmazonClientException;import com.amazonaws.AmazonServiceException;import com.amazonaws.auth.BasicAWSCredentials;import co......

经常把天聊死的胖子
今天
5
0
linux下查看cpu、memo、io、swap性能数据脚本

直接贴脚本: 1、cpu #!/bin/bashCurrentDate=`date -d today '+%Y%m%d'`CurrentTime=`date -d today '+%Y%m%d%H%M'`mytext="$CurrentTime\t`top -b -n 1 | grep Cpu\(s\......

郑加威
今天
5
0
MySQL之——查询重复记录、删除重复记录方法大全

MySQL之——查询重复记录、删除重复记录方法大全

安小乐
今天
2
0
spring容器启动,停止,关闭事件监听-ApplicationEvent

ApplicationEvent ApplicationEvent相当于一个事件,所有自定义事件都需要继承这个抽象类。在Eclipse中Ctrl+Shift+H调用类的层次结构列表,可以看到如下 Application下抽象子类ApplicationCo...

tantexian
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部