一、背景
将公司原生项目使用Flutter实现,其中与WebView交互这一块,原生用的是JSBridge,为了避免大量改动,决定Flutter端也采用JSBridge,插件flutter_jsbridge_plugin,测试期间发现,在低版本手机,与JS交互方面没问题,但是在高版本手机上,交互全都失效。
二、解决方案
情况一: WebView加载完成之前 无 JS交互
这种情况就比较简单,在该插件的源码中有一个init方法,这个方法就是在执行注入JS的操作。
class JsBridge {
WebViewController _webViewController;
Map<String, CallBackFunction> _callbacks = Map();
Map<String, BridgeHandler> _handlers = Map();
int _uniqueId = 0;
static final String _protocolScheme = "jsbridge://";
final String _fetchData = "${_protocolScheme}return/fetch";
final String _returnData = "${_protocolScheme}return/sendMsg/";
String _dartToJs =
"javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');";
void loadJs(WebViewController controller) {
_webViewController = controller;
init();
}
void init() {
if (_webViewController == null) {
throw "WebViewController must not null";
}
if (Platform.isIOS) {
_loadJs(init_script_ios);
} else {
_loadJs(init_script_android);
}
// test();
}
我们只需要在WebView的状态回调的函数中各进行init一次,保证JS注入是成功的。
WebView(
initialUrl: _web_url,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (controller) async {
_jsBridge.loadJs(controller);
_controller.complete(controller);
registerWebViewHandler();
},
navigationDelegate: (NavigationRequest request) {
if (_jsBridge.handlerUrl(request.url)) {
return NavigationDecision.navigate;
}
return NavigationDecision.prevent;
},
onPageStarted: (url) {
_jsBridge.init();
},
onPageFinished:(url) {
_jsBridge.init();
},
onProgress: (value) {
},
);
情况二: WebView加载完成之前 有 JS交互
这种情况一般是在WebView加载完成之前需要传给JS一些数据,目前我没有想到更好的处理方案,只有如下方法暂时处理,如果大家有更好的方案,欢迎在评论区告诉我,感谢!
onProgress: (value) {
if (value > 10) {
_jsBridge.init();
}else if (value > 20){
_jsBridge.init();
}else if (value > 30){
_jsBridge.init();
}else if (value > 40){
_jsBridge.init();
}else if (value > 50){
_jsBridge.init();
}else if (value > 60){
_jsBridge.init();
}else if (value > 70){
_jsBridge.init();
}else if (value > 80){
_jsBridge.init();
}else if (value > 90){
_jsBridge.init();
}
}
这样就能确保在网页加载完成之前注入JS成功,这种挺不严谨的,希望能有更好的解决方案。
后续
最近将之前使用的官方的webview插件 webview_flutter 替换成了 flutter_inappwebview,使用下来,这个插件比官方插件功能更加完善,并且流畅度更高。
1、flutter_inappwebview内部已经自己兼容了JSBridge,所以使用它,就不需要再接入flutter_jsbridge_plugin,直接按如下代码去交互即可:
onWebViewCreated: (controller) async {
_controller = controller;
controller
..addJavaScriptHandler(
handlerName: 'functionName',
// arguments是一个List,如果前端只传了一个元素,那就取arguments的第0个元素
callback: (arguments) {
var temp = {};
return temp;// 用return返回数据给前端
});
},
)
};