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

如何修复Flutter控制器dispose后调用的‘Consider checking `mounted`.’错误?

问题描述

我已经查阅了Riverpod仓库中编号为496的Issue,尝试了其中所有用户提供的解决方案后仍无法修复错误。以下是我的代码:

调用代码:

await controller.submit(
  …
);

控制器方法实现:

Future<void> createBroadcast(…) async {
 state = state.copyWith(value: const AsyncValue.loading());
  final value = await AsyncValue.guard(() async {
    …

    return await …;
  });
  state = state.copyWith(value: value);
}

错误日志:

I/flutter ( 1242): Bad state: Tried to use CreateBroadcastScreenController after dispose was called.
I/flutter ( 1242):
I/flutter ( 1242): Consider checking mounted.
I/flutter ( 1242): …

请问该如何修复这个错误?


修复方案

这个错误的核心是控制器已被销毁(dispose),但异步操作完成后仍尝试更新状态。以下是几种可行的修复方式:

1. 新增mounted状态检查(最直接)

在更新状态的关键节点,先判断控制器是否还处于挂载状态:

Future<void> createBroadcast(…) async {
  // 初始检查,避免已销毁时执行后续逻辑
  if (!mounted) return;

  state = state.copyWith(value: const AsyncValue.loading());
  
  final value = await AsyncValue.guard(() async {
    …
    return await …;
  });

  // 异步操作完成后再次检查,防止等待期间控制器被销毁
  if (!mounted) return;
  state = state.copyWith(value: value);
}

2. 给异步操作添加取消机制(更严谨)

如果你的异步操作支持取消(比如网络请求),可以在控制器销毁时终止操作,避免无效的状态更新:

import 'package:dio/dio.dart';

class CreateBroadcastScreenController extends StateNotifier<...> {
  final CancelToken _cancelToken = CancelToken();

  Future<void> createBroadcast(…) async {
    if (!mounted) return;
    state = state.copyWith(value: const AsyncValue.loading());

    try {
      // 传入取消令牌
      final result = await yourApiCall(cancelToken: _cancelToken);
      if (!mounted) return;
      state = state.copyWith(value: AsyncValue.data(result));
    } catch (e) {
      // 忽略取消操作引发的错误
      if (e is DioException && e.type == DioExceptionType.cancel) return;
      if (!mounted) return;
      state = state.copyWith(value: AsyncValue.error(e));
    }
  }

  @override
  void dispose() {
    // 销毁时取消异步操作
    _cancelToken.cancel('控制器已销毁');
    super.dispose();
  }
}

3. 规范控制器方法的调用时机

检查触发controller.submit()的场景,确保只有在页面/组件处于活跃状态时才调用:

// 例如在StatefulWidget的组件中
ElevatedButton(
  onPressed: mounted ? () => controller.submit(…) : null,
  child: const Text('提交'),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:47:32