flutter 解决webview加载重定向h5页面 返回重复加载问题

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});@overrideState<WebPageContainer> createState() => _WebPageContainerState();
}class _WebPageContainerState extends State<WebPageContainer> {late WebViewController controller;String url = '';bool _backEventTriggered = false;DateTime? _lastedPageFinishedTime;bool _pageIsFinished = false;@overridevoid initState() {super.initState();}@overridevoid didChangeDependencies() {final Map<String, dynamic>? arguments = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;if (arguments != null) {url = arguments['url'] ?? '';debugPrint('third---url:$url');}super.didChangeDependencies();_initWebViewController();}// web端调用// <button onclick="jump()">打开一个新的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),),);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/480739.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv9改进,YOLOv9引入CAS-ViT(卷积加自注意力视觉变压器)中AdditiveBlock模块,二次创新RepNCSPELAN4结构

摘要 CAS-ViT 是一种为高效移动应用设计的视觉Transformer。模型通过结合卷积操作与加性自注意机制,在保持高性能的同时显著减少计算开销,适合资源受限的设备如手机。其核心组件 AdditiveBlock 通过多维度信息交互和简化的加性相似函数,实现了高效的上下文信息整合,避免了…

【Leecode】Leecode刷题之路第62天之不同路径

题目出处 62-不同路径-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 62-不同路径-官方解法 方法1&#xff1a;动态规划 思路&#xff1a; 代码示例&#xff1a;&#xff08;Java&…

PostgreSQL在Linux环境下的常用命令总结

标题 登录PgSQL库表基本操作命令新建库表修改库表修改数据库名称&#xff1a;修改表名称修改表字段信息 删除库表pgsql删除正在使用的数据库 须知&#xff1a; 以下所有命令我都在Linux环境中执行验证过&#xff0c;大家放心食用&#xff0c;其中的实际名称换成自己的实际名称即…

分布式协同 - 分布式锁一二事儿

文章目录 导图Pre概述概述1. 分布式互斥和临界资源的协调2. 分布式锁的基本原理3. 分布式锁的实现方式a. 基于数据库实现的分布式锁b. 基于Redis实现的分布式锁c. 基于Zookeeper实现的分布式锁 4. 高并发场景下的分布式锁优化a. 分段锁&#xff08;Sharded Locks&#xff09;b.…

FFmpeg 简介与编译

1. ffmpeg 简介&#xff1a; FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec&#xff0c;为了保证高可移…

Ubuntu-20.04安装 terminator

Ubuntu-20.04安装 terminator sudo apt install terminator 安装成功之后&#xff0c;在ubuntu终端里执行命令 terminator & terminator 窗口分割 基本操作 1. 创建新终端 水平分割&#xff1a;按下 Ctrl Shift E 创建一个新的水平分屏。 垂直分割&#xff1a;按下 Ct…

(已解决)wps无法加载此加载项程序mathpage.wll

今天&#xff0c;在安装Mathtype的时候遇到了点问题&#xff0c;如图所示 尝试了网上的方法&#xff0c;将C:\Users\Liai_\AppData\Roaming\Microsoft\Word\STARTUP路径中的替换为32位的Mathtype加载项。但此时&#xff0c;word又出现了问题 后来知道了&#xff0c;这是因为64位…

shell第二次作业

1. 使用case实现成绩优良差的判断 read -p "请输入你的成绩&#xff1a;" score if ! [[ "$score" ~ ^[0-9]$ ]];then echo "请输入数字" exit 1 fi if [ "$score" -lt 0 ] || [ "$score" -gt 100 ];then echo …

Appflyer记录卸载事件

Appflyer官方文档 1.原理 1.AppsFlyer每天向Firebase Cloud Messaging&#xff08;FCM&#xff09;和 Apple Push Notification Services&#xff08;APNS&#xff09;发送一次API请求。 2.然后FCM和APNS会发送一条静默推送消息&#xff0c;用于判断用户设备上是否仍装有相关应…

【81-90期】Java核心面试问题深度解析:性能优化与高并发设计

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Java &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 文章题目&#xff1a;Java核心面试问题深度解析&#xff1a;性能优化与高并发设计 摘要&#xff1a; 本文聚…

“移门缓冲支架:为家庭安全加码”

在智能家居日益普及的今天&#xff0c;科技不仅改变了我们的生活方式&#xff0c;也提升了家居的安全。移门缓冲支架作为一项结合了现代技术的小型装置&#xff0c;正逐渐成为提升家庭安全的重要配件。它通过吸收门关闭时的冲击力、减缓关门速度以及减少噪音等多重功能&#xf…

vue element-ui的el-image 和 el-table冲突层级冲突问题问题preview-teleported

问题: 解决代码:preview-teleported <el-image style"width: 50px; height: 50px" :src"props.row.url" :zoom-rate"1.2" :max-scale"7":min-scale"0.2" :preview-src-list"[props.row.url]" :initial-index&…

VR云展让企业实现产品的多样展示

随着科技的飞速进步&#xff0c;各行各业的企业正经历着前所未有的快速发展&#xff0c;企业形象的升级变得尤为重要。在此背景下&#xff0c;VR线上展厅以其独特的沉浸式3D体验脱颖而出&#xff0c;近年来赢得了广泛关注与认可。该模式已广泛应用于企业、展会机构、市政单位等…

强化安全责任意识,传音开展第四届信息及隐私安全文化宣传周活动

为了让信息及隐私安全责任意识深入每一位员工心中&#xff0c;传音连续多年开展信息及隐私安全文化宣传活动。11月4日至15日&#xff0c;传音控股第四届信息及隐私安全文化宣传周活动&#xff08;以下简称“传音安全周”&#xff09;在重庆、深圳、上海、南昌及海外多个国家地区…

人工智能的微积分基础

目录 ​编辑 引言 微积分的基本概念 1. 导数 2. 积分 3. 微分方程 微积分在人工智能中的应用 1. 机器学习中的优化 2. 反向传播算法 3. 概率与统计 4. 控制理论 5. 自然语言处理中的梯度 6. 计算机视觉中的积分 7. 优化算法中的微积分 8. 微分几何在深度学习中的…

canal同步数据教程

canal简介 官网&#xff1a;https://github.com/alibaba/canal 主要是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff0c;是一个实时同步的方案。 基于日志增量订阅和消费的业务包括 数据库镜像数据库实时备份索引构建和实时维护(拆分异构索引、…

《Learn Three.js》学习(3)光源

前言&#xff1a; WebGL本身不支持光源&#xff0c;不使用three.js,则需使用着色程序来模拟光源。 学习大纲&#xff1a; Three.js中的光源 特定光源的使用时机 如何调整和配置所有光源的行为 如何创建镜头光晕 光源表 基础光源&#xff1a;THRER.AmbientLight、THERE.Point…

shell(9)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&…

【头歌实训:递归实现斐波那契数列】

头歌实训&#xff1a;递归实现斐波那契数列 文章目录 任务描述相关知识递归相关知识递归举例何时使用递归定义是递归的数据结构是递归的问题的求解方法是递归的 编程要求测试说明源代码&#xff1a; 任务描述 本关任务&#xff1a;递归求解斐波那契数列。 相关知识 为了完成…

回声消除延时估计的一些方法

在音频信号处理&#xff0c;尤其是在回声消除和语音通信中&#xff0c;延时估计是一个至关重要的任务。回声消除技术旨在减少或消除在语音通信中由于信号反射而产生的回声。为了有效地实现这一点&#xff0c;系统需要准确估计发送信号和接收信号之间的延迟。通过了解延迟&#…