网站影响seo的标签,汉鼎中国 网站建设,谷歌搜索官网,小程序设计软件long time no see. 如果觉得该方案helps#xff0c;点个赞#xff0c;评论打个call#xff0c;这是我前进的动力~
通常写法#xff1a;
项目里用的webview_flutter 正常webview处理返回事件
if (await controller.canGoBack()) {controller.goBack();
} else {Navigator…long time no see. 如果觉得该方案helps点个赞评论打个call这是我前进的动力~
通常写法
项目里用的webview_flutter 正常webview处理返回事件
if (await controller.canGoBack()) {controller.goBack();
} else {Navigator.pop(context);
}
就是h5历史栈一直退栈如果栈内元素只有一个了就直接关闭webview的页面了。 问题描述
正常情况是没问题的的。 比如A--B--C,一直触发返回事件的话逻辑是C--B,B--A, A直接关。 如果h5里有重定向的话就有问题了。 比如A(A1重定向到A2)--B--C,一直触发返回事件的话逻辑是C--B,B--A2, A2--A1--A2,A2--A1--A2... 导致webview界面一直退不出来。
解决方案
参考https://github.com/flutter/flutter/issues/137737拉到最下面 设定pageFinished后xxx毫秒内NavigationRequest触发判定为重定向。逻辑已知A1重定向A2此时触发返回事件A2返回到A1在A1准备重定向到A2的时候根据条件判断为重定向然后进行阻断并再次执行一次返回逻辑。 另外该issue原始代码还是有问题没有考虑到NavigationRequest可能跑在onPageFinished前面故自己添加了轮询等待的代码。 注意这只是workaround极端情况下并不能做到100%可靠。必要情况可以考虑跟h5相关开发约定不用重定向或改用其它方案。
自己在android设备上实测了下还是挺稳定的。 几种可以考虑的方案 1.修改flutter_webview源码上传到github然后在自己的仓库引用该库。(该方案可以自己去修改到android测和ios测的相关代码比如flutter_webview没提供忽略ssl证书报错和ssl证书检查的问题就可以通过该方式解决感兴趣的话可以上网查一查) 2.换webview的库比如用flutter_inappwebview该库提供更强大的原生api支持围绕这个库的api来尝试解决。也是很流行的库但不是官方flutter.dev出品。
解决代码
如下
class WebPageContainer extends StatefulWidget {const WebPageContainer({super.key});overrideStateWebPageContainer createState() _WebPageContainerState();
}class _WebPageContainerState extends StateWebPageContainer {late WebViewController controller;String url ;bool _backEventTriggered false;DateTime? _lastedPageFinishedTime;bool _pageIsFinished false;overridevoid initState() {super.initState();}overridevoid didChangeDependencies() {final MapString, dynamic? arguments ModalRoute.of(context)?.settings.arguments as MapString, dynamic?;if (arguments ! null) {url arguments[url] ?? ;debugPrint(third---url:$url);}super.didChangeDependencies();_initWebViewController();}// web端调用// button onclickjump()打开一个新的webpage/button// function jump() {// var msg https://www.baidu.com// if (toNewWebPage) {// toNewWebPage.postMessage(msg);// }// }// getStatusBarHeight用法// h5页面调用getStatusBarHeight同上// h5页面同时要定义onStatusBarHeightReceived该方法是flutter测获取完高度后调用的// 例如// function onStatusBarHeightReceived(height) {// // 显示状态栏高度// document.getElementById(statusBarHeight).innerText Status Bar Height: height;// }void _initWebViewController() {controller WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..setBackgroundColor(const Color(0x00000000))..setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {// debugPrint(WebPage onProgress $progress);},onPageStarted: (String url) {_pageIsFinished false;debugPrint(WebPage onPageStarted $url);},onPageFinished: (String url) async {debugPrint(WebPage onPageFinished $url);_pageIsFinished true;if (_backEventTriggered) {_lastedPageFinishedTime DateTime.now();} else {_lastedPageFinishedTime null;}},onWebResourceError: (WebResourceError error) {},onNavigationRequest: (NavigationRequest request) async {debugPrint(WebPage onNavigationRequest ${request.url});debugPrint(WebPage onNavigationRequest isMainFrame ${request.isMainFrame});//轮询因为onNavigationRequest可能跑在onPageFinished前面强制等待while (!_pageIsFinished) {await Future.delayed(Duration(milliseconds: 10));}if (_shouldApplyNavLockout()) {goBack(); //执行第二次backreturn NavigationDecision.prevent;}return NavigationDecision.navigate;},onUrlChange: (UrlChange change) {print(WebPage onUrlChange ${change.url});}),)..addJavaScriptChannel(destoryCurrentPage, onMessageReceived: (JavaScriptMessage message) {//h5自己的返回键返回到最后一步当前页面出栈debugPrint(destoryCurrentPage);Nav.pop();})..addJavaScriptChannel(toNewWebPage, onMessageReceived: (JavaScriptMessage message) {//允许h5页面打开新的third_web_pageNav.push(routerName: RouterPathModuleCommon.WebPageContainer, arguments: {url: message.message});})..addJavaScriptChannel(toLogin, onMessageReceived: (JavaScriptMessage message) {//login:有些h5页面跳转后需要登录的 logout:可能存在的h5页面提供登出功能Nav.push(routerName: RouterPathModuleAccount.LoginPage, arguments: {url: message.message});})..addJavaScriptChannel(getStatusBarHeight, onMessageReceived: (JavaScriptMessage message) {double statusBarHeight MediaQuery.of(context).padding.top;controller.runJavaScriptReturningResult(onStatusBarHeightReceived($statusBarHeight)).then((value) print(发送statusBarHeight成功));});controller.loadRequest(Uri.parse(url));}// 判断重定向的条件 最近一次pageFinished和navigationRequest小于xxx毫秒。 这只是个workaround并不是十全十美的方案bool _shouldApplyNavLockout() {final timestamp _lastedPageFinishedTime;_lastedPageFinishedTime null;// TODO make the threshold time configurable.if (timestamp ! null) {debugPrint(WebPage diff timestamp ${DateTime.now().difference(timestamp!)});}return timestamp ! null DateTime.now().difference(timestamp) const Duration(milliseconds: 150);}void goBack() async {if (await controller.canGoBack()) {_backEventTriggered true;controller.goBack();} else {Navigator.pop(context);}}overrideWidget build(BuildContext context) {return Scaffold(body: WillPopScope(onWillPop: () async {goBack();return false;},child: WebViewWidget(controller: controller),),);}
}