You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter多WebView组件报错:Bad state: Future already completed

解决"Bad state: Future already completed"异常问题

这个问题的根源非常明确:你把_controller这个Completer对象定义成了全局变量,所有PageWeb实例都会共享同一个Completer实例。

当第一个Tab的WebView完成初始化时,_controller.complete(webViewController)已经将这个Completer标记为"已完成"状态;当你切换到第二个Tab,第二个PageWeb的WebView尝试再次调用_controller.complete()时,就会触发异常——因为一个Completer对象只能被完成一次,不允许重复调用complete方法。

修复方案

把Completer<WebViewController>的定义移到_PageWebState类内部,让每个PageWeb实例都拥有自己独立的Completer:

修改你的pageweb.dart代码如下:

class PageWeb extends StatefulWidget {
  final delegate;
  final ObjectKey key;
  final String navTitle;
  PageWeb(this.delegate, this.key, this.navTitle);

  @override
  _PageWebState createState() {
    return _PageWebState();
  }
}

class _PageWebState extends State<PageWeb> {
  bool _isLoading = true;
  final cookieManager = WebviewCookieManager();
  // 将Completer移到State内部,每个PageWeb实例独立持有
  final Completer<WebViewController> _controller = Completer<WebViewController>();

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          middle: Text(widget.navTitle),
        ),
        child: SafeArea(
            child: Container(
                child: WebView(
          key: widget.key,
          initialUrl: "https://www.google.com/search?q=${widget.navTitle}",
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _controller.complete(webViewController); // 现在每个实例用自己的Completer,不会重复完成
          },
          onPageStarted: (String pageUrl) {
            setState(() {
              _isLoading = true;
            });
          },
          onPageFinished: (String pageUrl) {
            setState(() {
              _isLoading = false;
            });
          },
        ))));
  }
}

额外优化(可选)

如果你的父组件(_MyHomePageState)需要获取每个WebView的控制器,可以在PageWeb中暴露Future<WebViewController>的方式实现,比如:

class PageWeb extends StatefulWidget {
  // ... 现有代码
  // 添加getter让父组件可以获取controller的Future
  Future<WebViewController> get controller => _state._controller.future;
  _PageWebState _state;

  @override
  _PageWebState createState() {
    _state = _PageWebState();
    return _state;
  }
}

这样父组件就可以通过pageA.controller来获取对应WebView的控制器,同时也不会影响每个Tab的独立初始化流程。

内容的提问来源于stack exchange,提问作者klados

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:22:44