時下app分以下幾種技術選型
- Webapp,框架有cordova,ionic等
- Hybrid,即Native+h5方式
- React Native, weex方向
- 純Native,這個沒啥好說的
- flutter,明日之星 本文只描述Hybrid中的jsbrige部分實現原理,不會涉及Native部分的webview如何設計,關於webview的文章太多了,可以參考別的文章
通訊原理
預先定義好schema,如myapp://... 通過前端傳送偽連線請求iframe.src
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一個方法:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith(SCHEMA)) {
...
return true;
}
}
複製程式碼
引數傳遞
實際專案中,肯定是要傳遞引數給Native接收的,可以對這樣封裝
for (key in data) {
if (data.hasOwnProperty(key)) {
schema += '&' + key + data[key]
}
}
複製程式碼
這樣就可以拼接出&key=value這種形式,Native端可以寫一個方法獲取到key和value的值然後去做相應的處理。
方法回撥
有的時候bridge事件處理完之後需要告訴前端一些訊息回饋,那麼前端需要封裝一個callbackName傳給Native端
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端執行回撥寫法:
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封裝完畢後,可以測試,以分享為例:
window.bridge.share({
title: '...',
content: '...'
}, function (result) {
if (result.success) {
alert('分享成功')
}
})
複製程式碼
基於vue的封裝
只需載入brige.js即可
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端。