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

Flutter初始化调用异步方法触发组件已卸载State错误排查

问题分析

你当前的mounted判断只在getProductsData方法执行之初做了一次,但await Provider.of<Products>(context, listen: false).getProductsData()是异步操作,这段时间内组件可能已经被卸载(比如用户快速跳转页面)。当异步操作完成后,后续的Provider.of调用和setState依然会使用已经失效的context,导致报错。

解决方法

1. 异步操作完成后再次检查mounted状态

在await之后的每一步操作前,都要确认组件仍处于挂载状态,避免使用失效的context或调用setState。

2. 提前获取Provider实例

在initState里提前获取Products的Provider实例,避免后续多次调用Provider.of时依赖context,同时也能减少重复代码。

修改后的代码示例

@override
void initState() {
  super.initState();
  // 提前获取Provider实例,避免后续依赖context
  final productsProvider = Provider.of<Products>(context, listen: false);
  getProductsData(productsProvider);
  textController = TextEditingController();
  SchedulerBinding.instance.addPostFrameCallback((_) {
    final authProvider = Provider.of<Auth>(context, listen: false);
    String otpMessage = authProvider.userRegMessage;
    if (otpMessage.isNotEmpty && mounted) { // 这里也加mounted判断
      GlobalSnackBar.show(context, otpMessage);
    }
    authProvider.userRegMessage = "";
  });
}

Future<void> getProductsData(Products productsProvider) async {
  await productsProvider.getProductsData();
  // 异步操作完成后,先检查组件是否还挂载
  if (!mounted) return;
  
  products = productsProvider.productDataList;
  setState(() {
    productDataLoading = false;
  });
}

额外优化建议

如果你的getProductsData网络请求支持取消(比如使用dio的CancelToken),可以在组件dispose方法中取消未完成的请求,避免不必要的资源消耗和后续错误:

CancelToken? _cancelToken;

@override
void initState() {
  super.initState();
  _cancelToken = CancelToken();
  final productsProvider = Provider.of<Products>(context, listen: false);
  getProductsData(productsProvider);
  // ...其他代码
}

Future<void> getProductsData(Products productsProvider) async {
  try {
    await productsProvider.getProductsData(cancelToken: _cancelToken);
    if (!mounted) return;
    products = productsProvider.productDataList;
    setState(() {
      productDataLoading = false;
    });
  } on DioException catch (e) {
    if (e.type == DioExceptionType.cancel) {
      // 请求已取消,无需处理
      return;
    }
    // 处理其他错误
  }
}

@override
void dispose() {
  _cancelToken?.cancel();
  textController.dispose();
  super.dispose();
}

内容的提问来源于stack exchange,提问作者rudr'a rajput

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:52:57