时下app分以下几种技术选型
- Webapp,框架有cordova,ionic等
- Hybrid,即Native h5方式
- React Native, weex方向
- 纯Native,这个没啥好说的
- flutter,明日之星 本文只描述Hybrid中的jsbrige部分实现原理,不会涉及Native部分的webview如何设计,关于webview的文章太多了,可以参考别的文章
通信原理
预先定义好schema,如myapp://... 通过前端发送伪连接请求iframe.src
代码语言:javascript复制 var iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = schema
var body = document.body
body.appendChild(iframe)
setTimeout(function () {
body.removeChild(iframe)
iframe = null
})
复制代码
可以看到,在某个按钮或者行为需要与原生端通信时创建一个iframe然后再移除,如果不移除iframe,则会在body里出现大量无用的iframe标签,这里简单说一下Native怎么去拦截这个伪链接请求。 在WebviewClient里override一个方法:
代码语言:javascript复制 @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(SCHEMA)) {
...
return true;
}
}
复制代码
参数传递
实际项目中,肯定是要传递参数给Native接收的,可以对这样封装
代码语言:javascript复制 for (key in data) {
if (data.hasOwnProperty(key)) {
schema = '&' key data[key]
}
}
复制代码
这样就可以拼接出&key=value这种形式,Native端可以写一个方法获取到key和value的值然后去做相应的处理。
方法回调
有的时候bridge事件处理完之后需要告诉前端一些消息回馈,那么前端需要封装一个callbackName传给Native端
代码语言:javascript复制 var callbackName = ''
if (typeof callback === 'string') {
callbackName = callback
} else {
callbackName = action Date.now()
console.log('callbackName: ' callbackName)
window[callbackName] = callback
}
schema = 'callback=' callbackName
复制代码
特别注意:这里有一个Date.now(),作用是为了避免回调方法重复,且避免在ios手机上不断点击造成界面阻塞UI失去响应。
Native端执行回调写法:
代码语言:javascript复制 public static void call(WebView webview, String js) {
if (webview != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webview.evaluateJavascript(js, null);
} else {
webview.loadUrl("javacript:" js);
}
}
}
复制代码
用法举例
jsbrige封装完毕后,可以测试,以分享为例:
代码语言:javascript复制 window.bridge.share({
title: '...',
content: '...'
}, function (result) {
if (result.success) {
alert('分享成功')
}
})
复制代码
基于vue的封装
只需载入brige.js即可
代码语言:javascript复制import './bridge'
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount('#app')
复制代码
总结
- 在ios上不要使用UIWebview,使用WkWebview。
- android要注意webview内存泄漏问题。
- 前端要控制打包体积,不推荐用webpack,因为会生成大量的webpack的封装代码。
- 推荐使用rollup轻量级前端工程化打包,不会生成多余的js代码。
- 推荐使用多页模式,Native端通过pushwindow等方法,把跳转权交给Native端。