Flutter中WebView加载失败时如何从Assets加载自定义HTML
解决webview_flutter中onWebResourceError先于onWebViewCreated执行的问题
方案一:缓存错误事件,等待控制器初始化后处理
通过变量缓存错误信息,等控制器创建完成后再执行错误页面加载逻辑,避免因控制器未就绪导致的空指针问题。
修改后的代码示例:
WebViewController? webViewController; WebResourceError? _pendingError; @override Widget build(BuildContext context) { return SafeArea( child: WebView( initialUrl: widget.url, javascriptMode: JavascriptMode.unrestricted, allowsInlineMediaPlayback: true, debuggingEnabled: true, userAgent: "", onWebViewCreated: (controller) { webViewController = controller; // 控制器初始化完成后,检查是否有待处理的错误 if (_pendingError != null) { controller.loadFlutterAsset("assets/error.html"); _pendingError = null; } }, initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow, onWebResourceError: (webResourceError) { // 控制器未就绪时缓存错误,否则直接加载错误页 if (webViewController == null) { _pendingError = webResourceError; } else { webViewController?.loadFlutterAsset("assets/error.html"); } }, ), ); }
方案二:调整加载顺序,先初始化控制器再加载目标URL
让WebView先加载空白页确保控制器优先创建完成,之后再加载目标业务URL,这样后续的错误回调能直接拿到可用的控制器。
代码示例:
WebViewController? webViewController; @override Widget build(BuildContext context) { return SafeArea( child: WebView( initialUrl: "about:blank", // 先加载空白页触发控制器初始化 javascriptMode: JavascriptMode.unrestricted, allowsInlineMediaPlayback: true, debuggingEnabled: true, userAgent: "", onWebViewCreated: (controller) { webViewController = controller; // 控制器就绪后再加载目标URL controller.loadUrl(widget.url); }, initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow, onWebResourceError: (webResourceError) { webViewController?.loadFlutterAsset("assets/error.html"); }, ), ); }
方案三:用Completer异步等待控制器就绪
利用Completer封装控制器的初始化过程,在错误回调中异步等待控制器创建完成后执行加载逻辑。
代码示例:
final Completer<WebViewController> _controllerCompleter = Completer(); @override Widget build(BuildContext context) { return SafeArea( child: WebView( initialUrl: widget.url, javascriptMode: JavascriptMode.unrestricted, allowsInlineMediaPlayback: true, debuggingEnabled: true, userAgent: "", onWebViewCreated: (controller) { _controllerCompleter.complete(controller); }, initialMediaPlaybackPolicy: AutoMediaPlaybackPolicy.always_allow, onWebResourceError: (webResourceError) async { // 等待控制器初始化完成 final controller = await _controllerCompleter.future; controller.loadFlutterAsset("assets/error.html"); }, ), ); }
以上三种方案均可解决你遇到的问题,你可以根据项目实际场景选择合适的实现方式。
内容的提问来源于stack exchange,提问作者ammcom
相关产品推荐
相关产品推荐

