Flutter中调用dispose后使用EndUserViewModel报错求助
问题原因
你在initState里的mounted检查仅保证调用loadEndUser时组件存在,但fetchEndUser是异步API请求,请求完成时组件可能已被销毁,且EndUserViewModel也可能已执行dispose,此时再访问ViewModel就会触发报错。
解决方案
方案1:在异步操作关键节点检查状态
取消initState里多余的mounted判断(initState执行时组件必然处于挂载状态),在API请求前后、访问ViewModel属性前,分别检查组件和ViewModel的可用状态:
@override void initState() { super.initState(); loadEndUser(); // initState阶段组件一定处于mounted状态,无需额外判断 } loadEndUser() async { WidgetsBinding.instance.addPostFrameCallback((_) async { // 检查组件是否仍挂载 if (!mounted) return; // 获取ViewModel实例 final endUserViewModel = ref.read(endUserViewModelProvider.notifier); // 检查ViewModel是否仍可用 if (!endUserViewModel.mounted) return; // 执行异步API请求 await endUserViewModel.fetchEndUser("user02@gmail.com"); // 请求完成后再次检查状态 if (!mounted || !endUserViewModel.mounted) return; // 访问ViewModel数据 final endUser = endUserViewModel.endUserList; final endUserData = endUser?.first.name; print(" DATA $endUser"); print("USER $endUserData"); }); }
方案2:取消未完成的API请求(更彻底)
如果你的API请求使用Dio等支持取消的库,可以在组件销毁时主动取消请求,避免后续无效操作:
1. 修改ViewModel的fetchEndUser方法,支持取消令牌
class EndUserViewModel extends StateNotifier<EndUserState> { CancelToken? _fetchCancelToken; EndUserViewModel() : super(EndUserState.initial()); Future<void> fetchEndUser(String email, {CancelToken? cancelToken}) async { _fetchCancelToken = cancelToken ?? CancelToken(); try { // 示例:使用Dio发起请求并传入取消令牌 final response = await Dio().get( 'your-api-url/end-user', queryParameters: {'email': email}, cancelToken: _fetchCancelToken, ); // 更新ViewModel状态 state = state.copyWith(endUserList: [...response.data]); } on DioException catch (e) { if (e.type == DioExceptionType.cancel) { // 请求被取消,直接返回不处理错误 return; } // 处理其他API错误 state = state.copyWith(error: e.message); } finally { _fetchCancelToken = null; } } @override void dispose() { // ViewModel销毁时取消未完成的请求 _fetchCancelToken?.cancel("ViewModel已销毁"); super.dispose(); } }
2. 在组件中管理取消令牌
CancelToken? _fetchCancelToken; @override void initState() { super.initState(); loadEndUser(); } loadEndUser() async { WidgetsBinding.instance.addPostFrameCallback((_) async { if (!mounted) return; _fetchCancelToken = CancelToken(); final endUserViewModel = ref.read(endUserViewModelProvider.notifier); await endUserViewModel.fetchEndUser( "user02@gmail.com", cancelToken: _fetchCancelToken, ); if (!mounted || !endUserViewModel.mounted) return; final endUser = endUserViewModel.endUserList; final endUserData = endUser?.first.name; print(" DATA $endUser"); print("USER $endUserData"); }); } @override void dispose() { // 组件销毁时取消未完成的请求 _fetchCancelToken?.cancel("组件已销毁"); super.dispose(); }
内容的提问来源于stack exchange,提问作者Farhana Akter
相关产品推荐
相关产品推荐

