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

Flutter页面返回触发已卸载Widget状态异常,mounted判断无效求助

解决Widget已卸载时调用setState的异常

问题场景

为避免initState中调用服务报错,改用didChangeDependencies方法获取数据更新页面,页面加载正常,但返回上一页时触发异常:

Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.

尝试过mounted状态判断、重写setState方法均无效,重写的setState代码如下:

@override
void setState(VoidCallback fn) {
  if (mounted) {
    super.setState(fn);
  }
}

相关业务代码:

List<DetailObjects?> onOdemeDetay = [];

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  OnOdemeListeClass().fetchList(context).then((value) {
    final checkData = Provider.of<LoginInfo>(context, listen: false);
    if (mounted) {
      setState(() {
        if (value != null && value.detailObjects != null) {
          onOdemeDetay = value.detailObjects!;
          checkData.updateLabel(onOdemeDetay[0]?.label);
          checkData.updateValue(onOdemeDetay[0]?.value);
        }
      });
    }
  });
}

有效解决方案

1. 用CancelableOperation取消异步任务

在State类中维护异步任务的可取消实例,在Widget销毁时主动取消任务,避免回调执行时操作已卸载的State:

import 'package:async/async.dart';

CancelableOperation? _fetchOperation;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 先取消已有任务,避免重复请求
  _fetchOperation?.cancel();
  _fetchOperation = CancelableOperation.fromFuture(
    OnOdemeListeClass().fetchList(context),
  ).then((value) {
    if (!mounted) return;
    final checkData = Provider.of<LoginInfo>(context, listen: false);
    setState(() {
      if (value != null && value.detailObjects != null) {
        onOdemeDetay = value.detailObjects!;
        checkData.updateLabel(onOdemeDetay[0]?.label);
        checkData.updateValue(onOdemeDetay[0]?.value);
      }
    });
  }).catchError((error) {
    // 忽略任务取消的错误
    if (error is OperationCanceledError) return;
    // 处理其他请求错误
  });
}

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

2. 优化Provider调用与上下文判断

Flutter 3.7+支持直接通过context.mounted判断Widget状态,同时提前获取Provider实例,避免在异步回调中使用已失效的上下文:

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 提前获取Provider实例,避免回调中使用无效context
  final checkData = Provider.of<LoginInfo>(context, listen: false);
  OnOdemeListeClass().fetchList(context).then((value) {
    if (!context.mounted) return;
    setState(() {
      if (value != null && value.detailObjects != null) {
        onOdemeDetay = value.detailObjects!;
        checkData.updateLabel(onOdemeDetay[0]?.label);
        checkData.updateValue(onOdemeDetay[0]?.value);
      }
    });
  });
}

3. 控制请求仅触发一次

didChangeDependencies会在依赖变化时多次执行,添加标记避免重复发起请求:

bool _hasFetched = false;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  if (!_hasFetched) {
    _hasFetched = true;
    // 执行请求逻辑...
  }
}

核心原因

异步请求完成时Widget已卸载,mounted判断可能因时机问题失效,或回调中使用了已失效的上下文。通过主动取消异步任务、提前获取依赖、控制请求次数,可从根源避免异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 11:22:37