Flutter evaluateJavascript仅生效一次,Android需卸载清缓存恢复
问题解决:Flutter WebView注入JS仅生效一次(Android专属问题)
核心问题分析
你当前使用的DOMSubtreeModified是已废弃的DOM事件API,Android系统的WebView内核(基于Chromium)对该API的实现存在兼容性问题,多次触发后可能被浏览器主动节流或失效,导致后续DOM变化时无法重新绑定事件。而iOS的WebKit内核对废弃API的兼容性处理更宽松,因此未出现问题。此外,反复对元素执行off('click').on('click')也可能导致事件绑定逻辑混乱,在Android上积累错误状态。
解决方案1:使用事件委托(推荐)
无需监听DOM变化,直接将点击事件委托到document上,不管目标元素何时动态生成,都能触发回调。这种方式更高效稳定:
await webViewController.evaluateJavascript(source: """ document.addEventListener('click', function(e) { const target = e.target; if (target.tagName === 'A' && target.href.startsWith('/GenericUpload/GetFile')) { e.preventDefault(); // 阻止默认跳转行为 window.flutter_inappwebview.callHandler('MobileAppDownload', target.href); } }, true); """);
解决方案2:替换为MutationObserver(标准DOM监听API)
如果必须监听DOM变化,用标准的MutationObserver替代废弃的DOMSubtreeModified,它能精准控制监听范围,避免不必要的性能损耗:
await webViewController.evaluateJavascript(source: """ // 配置观察规则:监听子元素的添加/移除 const observerConfig = { childList: true, subtree: true }; const targetNode = document.body; const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { // 仅处理新增节点的情况 if (mutation.addedNodes.length > 0) { document.querySelectorAll("a[href^='/GenericUpload/GetFile']").forEach(link => { // 先移除已有绑定,避免重复触发 link.removeEventListener('click', handleDownloadClick); link.addEventListener('click', handleDownloadClick); }); } }); }); // 定义统一的点击处理函数 function handleDownloadClick(e) { e.preventDefault(); window.flutter_inappwebview.callHandler('MobileAppDownload', this.href); } // 启动DOM观察 observer.observe(targetNode, observerConfig); // 初始化时绑定已有元素 document.querySelectorAll("a[href^='/GenericUpload/GetFile']").forEach(link => { link.addEventListener('click', handleDownloadClick); }); """);
额外Android适配建议
- 检查WebView缓存设置,避免页面缓存旧的JS逻辑:
WebView( initialUrl: "your_target_url", javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (controller) { controller.settings.cacheMode = WebSettings.LOAD_NO_CACHE; }, ) - 确保JS注入时机正确,建议在
onPageFinished回调中执行注入,避免页面未加载完成时DOM不存在的问题。
内容的提问来源于stack exchange,提问作者Mohamed Samy
相关产品推荐
相关产品推荐

