今日科技快讯
近日,滴滴顺风车披露了一组数字,预测春运前后,跨城出行以7天为一个周期,呈“潮汐式”变化。2月13号,有将近100万人乘滴滴顺风车踏上归途;除夕当天,还有近40万在回家的顺风车上。返程巅峰集中在2月23日前后,23日预计有超过110万人乘坐滴滴顺风车返回工作岗位。
作者简介
本篇文章来自juexingzhe的投稿。主要介绍了Android与JS的交互框架JsBridge源码分析的相关知识,希望对大家有所帮助!
juexingzhe的博客地址:
https://www.jianshu.com/u/ea71bb3770b4
前言
在Android开发中,由于Native开发的成本较高,H5页面的开发更灵活,修改成本更低,因此前端网页JavaScript(下面简称JS)与Java之间的互相调用越来越常见。
JsBridge就是一个简化Android与JS通信的框架,源码地址:
https://github.com/lzyzsd/JsBridge
正文
我们今天通过一个简单例子来分析下开源框架JsBridge的源码。例子的代码我也放在Github,有需要的可以seesee:
https://github.com/juexingzhe/Android_JS
例子很简单,随便输入信息登陆,会加载一个H5页面,在H5界面点击按钮,Java执行getUserInfo()然后将UserInfo回传给JS,H5页面再显示UserInfo。
1.png
2.png
3.png
JS调用Android基本有下面三种方式
webView.addJavascriptInterface()
WebViewClient.shouldOverrideUrlLoading()
WebChromeClient.onJsAlert()/onJsConfirm()/onJsPrompt() 方法分别回调拦截JS对话框alert()、confirm()、prompt()消息
Android调用JS
webView.loadUrl();
webView.evaluateJavascript()
常用方法的使用后面例子中会用到,更细节的介绍各位同学可以去网上搜搜看看。
JsBridge使用
我们先来看下Java层的代码,首先引入依赖和仓库
准备工作就是这样,下面可以开始撸代码,首先就是点击按钮登陆,这个简单:
布局文件中要使用BridgeWebView:
在跳转后的页面,获取登陆信息并存储,再通过loadUrl加载H5页面:
主要是要注册Handler,供JS调用,getUserInfo就是注册供JS调用的Handler的id,data是JS传过来的参数,CallBackFunction 函数中需要把JS需要的response返回给JS
Java层的代码就这么简单,下面看下JS层工作:
首先需要一个js文件,我们写一个getuserinfo.html文件放在assets目录下,文件内容,不建议把js代码直接放在html文件中,我为了方便直接就写在这了。代码放了两个段落,一个类似于TextView用来显示用户信息,一个Button。点击按钮会调用callHandler,三个参数和Java层一一对应,在Java层返回的时候,会调用function(responseData)函数,显示用于信息。
使用基本就是这样了,可以看出来JsBridge通过封装,JS和Java之间的通信只需要实现两个步骤,使用起来很方便。
JsBridge源码分析
分析之前我把JS调用Java画了个简易交互图,Java调用JS的过程类似:
4.png
是不是感觉反而更复杂了???其实只要捉住主要的三点,JsBridge就原形毕露:
Android调用JS是通过loadUrl(url),url中可以拼接要传给JS的对象
JS调用Android是通过shouldOverrideUrlLoading
JsBridge将沟通数据封装成Message,然后放进Queue,再将Queue进行传输
接下来我们来一步一步跟踪上面例子的调用过程:
JS层点击按钮调用callHandler
handlerName,Java和JS要一致,data是Java层handlerName函数执行的参数。responseCallback是Java执行完handlerName返回时,JS回调的接口,是JS执行
callHandler会调用_doSend。如果JS需要回调,就将回调的callbackId放进message中,Java执行完会传回callbackId,这里是cb_1_1495182409011,构造完message放进队列sendMessageQueue。通过iframe属性给Java发送通知消息,消息结构为:
yy://QUEUE_MESSAGE/
Java收到通知消息
WebView在shouldOverrideUrlLoading拦截到url:yy://QUEUE_MESSAGE/
然后会执行webView.flushMessageQueue(),在主线程执行loadUrl通知JS层推送队列到Java;
JS 发送Request Queue
执行_fetchQueue,将sendMessageQueue转化成JSON。通过iframe属性给Java发送通知消息。
Java收到调用通知
进行处理并发送Response Queue到JS,WebView在shouldOverrideUrlLoading会拦截到url,执行webView.handlerReturnData(url);根据函数名_fetchQueue拿到之前注册的回调函数CallBackFunction returnCallback,执行回调函数,并且从注册中移除。
接下来就是对Request Queue的解析然后找到JS希望调用Handler并且执行,代码中我写了注释,可以直接看:
那么这个handler是什么?就是Java调用registerHandler注册的getUserInfo
上面的function就是在flushMessageQueue 解析时构造的responseFunction,在message中包括JS层需要回调的函数Id,然后就是getUserInfo执行的结果。调用queueMessage
通过构造String指令,然后loadUrl执行JS代码,注意对象也是通过这样方式传递过去的,就类似调用本地函数,不发起网络请求
其中
JS收到Response JSON
来到_handleMessageFromNative
最后都会调用到_dispatchMessageFromNative,由于是JS主动调用Java,因此有responseId,执行registerHandler时传入的CallBack,也就是显示用户信息。我在代码里加了注释,很容易看懂。
源码的分析就到这结束了,代码不多,但是封装的接口很是好用。
总结
最后总结下,使用上很方便主要两个步骤
被调用方注册Handler
调用方调用Handler
原理上还是那三句话,请原谅我从上面直接copy过来:
Android调用JS是通过loadUrl(url),url中可以拼接要传给JS的对象
JS调用Android是通过shouldOverrideUrlLoading
JsBridge将沟通数据封装成Message,然后放进Queue,再将Queue进行传输
好了,今天我们JsBridge的使用和源码分析就到这了,谢谢!
文中例子的链接:
https://github.com/juexingzhe/Android_JS
领取专属 10元无门槛券
私享最新 技术干货