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

Flutter可加载更多ListView实现搜索功能调用API时出现Widget已卸载异常

异常触发原因

这个报错是因为你的异步操作回调执行时,当前页面的State已经被销毁了:
你在_loadData、onSearchTextChanged、列表项点击事件里发起的API请求,还有_loadMoreData里的延时操作都是异步任务,这些任务的回调不会因为页面退出就停止执行。如果用户在请求还没返回的时候就关闭了当前页面,State已经被卸载,此时回调里再执行setState更新页面、或者用context执行路由跳转,就会触发这个异常。

修复方案

你可以按照以下步骤修改代码:

  • 所有setState执行前先判断mounted状态
    mounted是Flutter State自带的属性,为true表示当前State还挂载在页面上,只有符合这个条件才能执行setState。
    举个修改_loadData的例子:
void _loadData() async {
  await StorageUtil.getInstance();
  String cookie = StorageUtil.getString('sess');
  String page = currentPage.toString();

  if (cookie != null) {
    ApiService.getEstimateList(cookie, page, myAllestimate, search)
        .then((value) {
      // 增加mounted判断,已卸载就直接返回不执行后续逻辑
      if (!mounted) return;
      if (value.data != null) {
        if (count < _totalRecords) {
          setState(() {
            invoicelist.addAll(value.data);
            print(value.data);
            _totalRecords = value.recordsTotal;
          });
          print(
              'List size is $count and TotalRecord - ${value.recordsTotal} , TotalFiltered - ${value.recordsFiltered}');
        }
      }
    });
  }
}

所有异步回调里的setState都要按照这个逻辑增加mounted判断,包括onSearchTextChanged里的回调。

  • 异步操作中使用context前先判断mounted
    比如列表项点击事件里的路由跳转,修改示例:
ApiService.viewInvoice(cookie, id, bmaster, 'estimate')
    .then((value) {
  // 增加mounted判断
  if (!mounted) return;
  if (value != null) {
    var result = jsonDecode(value);
    if (result['status'].toString() == '1') {
      var decode = Uri.decodeFull(result['url']);
      var pdf_url = Uri.decodeFull(result['pdf_url']);
      pdfUrl = pdf_url.toString();
      weburl = decode.toString();
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => WebViewContainer(
              weburl, 'Estimate', pdfUrl, mobile, id, custId),
        ),
      );
    }
  }
});
  • 优化_loadMoreData的异步逻辑
    你当前的_loadMoreData没有等待_loadData执行完成就直接返回了true,会导致加载更多状态异常,修改为:
Future<bool> _loadMoreData() async {
  print('_loadMoreData()');
  await Future.delayed(Duration(milliseconds: 1000));
  currentPage += 1;
  await _loadData(); // 增加await等待数据加载完成
  return true;
}
  • 可选优化:页面销毁时取消未完成的请求
    如果要更彻底的规避问题,可以给API请求增加取消标记(比如Dio的CancelToken),重写dispose方法,在页面销毁时主动取消所有未完成的异步请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:39:00