文档章节

JsBridge原理分析

Kingguary
 Kingguary
发布于 06/21 21:24
字数 1231
阅读 19
收藏 0
点赞 0
评论 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
博文 70
码字总数 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
【quickhybrid】JS端的项目实现

前言 API实现阶段之JS端的实现,重点描述这个项目的JS端都有些什么内容,是如何实现的。 不同于一般混合框架的只包含JSBridge部分的前端实现,本框架的前端实现包括JSBridge部分、多平台支持...

dailc
07/01
0
0
Phonegap 通信原理

下图为JavaScript调用本地代码的通信过程 Phonegap的核心API都是基于插件的,这些JavaScript API都会调用cordova.exec() 函数来完成操作。cordova.exec()函数如下 cordova.exec(success, fa...

zting科技
2017/12/16
0
0
UIWebView与JavaScript的那些事儿

UIWebView是IOS SDK中渲染网面的控件,在显示网页的时候,我们可以hack网页然后显示想显示的内容。其中就要用到javascript的知识,而UIWebView与javascript交互的方法就是stringByEvaluatin...

长平狐
2012/08/13
549
0
【Android】如何写一个JsBridge

JsBridge 简介 Android JsBridge 就是用来在 Android app的原生 java 代码与 javascript 代码中架设通信(调用)桥梁的辅助工具。 原文地址点这里 github点这里 使用方式戳这里 有问题请联系...

xesam
2016/04/13
257
2
H5 与 Native 交互之 JSBridge 技术

做过混合开发的很多人都知道Ionic和PhoneGap之类的框架,这些框架在web基础上包了一层Native,然后通过Bridge技术使得js可以调用视频、位置、音频等功能。本文就是介绍这层Bridge的交互原理,...

有赞前端
2017/08/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

tomcat虚拟路径的几种配置方法

tomcat虚拟路径的几种配置方法 一般我们都是直接引用webapps下面的web项目,如果我们要部署一个在其它地方的WEB项目,这就要在TOMCAT中设置虚拟路径了,Tomcat的加载web顺序是先加载 $Tomcat_ho...

Helios51
6分钟前
1
0
Mac 安装jupyter notebook的过程

MAC台式机 python:mac下自带Python 2.7.10 1.先升级了pip安装工具:sudo python -m pip install --upgrade --force pip 2.安装setuptools 工具:sudo pip install setuptools==33.1.1 3.安装......

火力全開
12分钟前
0
0
导航守卫解释与例子

“导航”表示路由正在发生改变。 正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。 记住...

tianyawhl
12分钟前
0
0
Java日志框架-logback配置文件多环境日志配置(开发、测试、生产)(原始解决方法)

说明:这种方式应该算是最通用的,原理是通过判断标签实现。 <!-- if-then form --> <if condition="some conditional expression"> <then> ... </then> </if> ......

浮躁的码农
26分钟前
1
0
FTP传输时的两种登录方式和区别

登录方式 匿名登录 用户名为: anonymous。 密码为:任何合法 email 地址。 授权登录 用户名为:用户在远程系统中的用户帐号。 密码为:用户在远程系统中的用户密码。 区别 匿名登录 只能访问...

寰宇01
27分钟前
0
0
plsql developer 配置监听(不安装oracle客户端)

plsql developer 配置监听(不安装oracle客户端)

微小宝
34分钟前
0
0
数据库(分库分表)中间件对比

本人的宗旨就是,能copy的,绝对不手写。 分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm。 根据一定的规则把数据文件(MYD)和索...

奔跑吧代码
38分钟前
2
0
Netty与Reactor模式详解

在学习Reactor模式之前,我们需要对“I/O的四种模型”以及“什么是I/O多路复用”进行简单的介绍,因为Reactor是一个使用了同步非阻塞的I/O多路复用机制的模式。 I/O的四种模型 I/0 操作 主要...

hutaishi
44分钟前
1
0
【2018.07.16学习笔记】【linux高级知识 20.16-20.19】

20.16/20.17 shell中的函数 20.18 shell中的数组 20.19 告警系统需求分析

lgsxp
50分钟前
0
0
用 D3.js 画一个手机专利关系图, 看看苹果,三星,微软间的专利纠葛

用 D3.js 画一个手机专利关系图, 看看苹果,三星,微软间的专利纠葛 前言 本文灵感来源于Mike Bostock 的一个 demo 页面 原 demo 基于 D3.js v3 开发, 笔者将其使用 D3.js v5 进行重写, 并改为...

ssthouse_hust
54分钟前
19
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部