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

如何解决Flutter中setState() called after dispose()异常?

管理员注册页面点击按钮后加载条触发setState disposed异常

点击「注册为管理员」按钮后尝试显示加载条,但触发如下异常,无法正常实现加载功能:

[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: setState() called after dispose(): _AdminRegisterState#f3c8f(lifecycle state: defunct, not mounted)
E/flutter (29660): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (29660): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (29660): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (29660): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1073:9)
E/flutter (29660): #1      State.setState (package:flutter/src/widgets/framework.dart:1108:6)
E/flutter (29660): #2      _AdminRegisterState.addAndCreateUser (package:election/pages/Admin/AdminRegister.dart:94:5)
E/flutter (29660): <asynchronous suspension>
E/flutter (29660): #3      _AdminRegisterState.build.<anonymous closure> (package:election/pages/Admin/AdminRegister.dart:215:31)
E/flutter (29660): <asynchronous suspension>
E/flutter (29660):  

问题代码(AdminRegister.dart)

import 'dart:math';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:election/pages/Admin/AdminHome.dart';
import 'package:election/services/Validator.dart';
import 'package:flutter/material.dart';
import 'package:election/services/Auth.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:loader_overlay/loader_overlay.dart';

class AdminRegister extends StatefulWidget {
  const AdminRegister({Key? key}) : super(key: key);

  @override
  State<AdminRegister> createState() => _AdminRegisterState();
}

class _AdminRegisterState extends State<AdminRegister> {
  String? get _errorText {
    final text = _controllerpassword.value.text;
    if (text.isEmpty) {
      return 'Can\'t be empty';
    }
    if (text.length < 8) {
      return 'atleast 8 characters requierd';
    }
    return null;
  }

  String? errormessage = '';
  String? errorAddUser = '';

  late String Name;
  late String Email;
  late String Phone;
  late String Password;
  late String Admin_Key;

  bool _istrue = true;
  bool _isloading = false;

  final TextEditingController _controllerName = TextEditingController();
  final TextEditingController _controlleremail = TextEditingController();
  final TextEditingController _controllerphone = TextEditingController();
  final TextEditingController _controllerpassword = TextEditingController();
  final TextEditingController _controllerrepassword = TextEditingController();
  final TextEditingController _controllerAdminKey = TextEditingController();

//create user metheod using firebase auth
  Future<void> createUserWithEmailAndPassword() async {
    setState(() { _isloading = true; });
    try {
      await Auth().createUserwithEmailAndPassword(email: _controlleremail.text, password: _controllerpassword.text);
      if(mounted){
        Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) =>  AdminHome()),(route) => false);
      }else{return;}
    } on FirebaseAuthException catch (e) {
      setState(() {
        errormessage = e.message;
      });
    }
    setState(() { _isloading = false; });
  }

  //cloud firestore using firestore
  final CollectionReference Admins = FirebaseFirestore.instance.collection('Admins');

  Future<void>addUser()async{
    Name = _controllerName.text;
    Email=_controlleremail.text;
    Password=_controllerpassword.text;
    Phone=_controllerphone.text;
    Admin_Key=_controllerAdminKey.text;
    try{
      await Admins.doc(Email).set({
        "Name":Name,"email":Email,"password":Password,"phone":Phone,"Admin":_istrue,"private_key":Admin_Key});
      print('user added successfullyyyyyyy');
    }catch(err){

    }
  }

  Future<void>addAndCreateUser()async{
    setState(() { _isloading = true; });
    await createUserWithEmailAndPassword();
    await addUser();
    setState(() { _isloading = false; });
  }

  Widget _errorMessage() {
    return Text(errormessage == '' ? '' : 'Humm $errormessage');
  }

  @override
  Widget build(BuildContext context) {
    if(_isloading){
      return const Scaffold(
        backgroundColor: Colors.cyan,
        body: Center(
          child: CircularProgressIndicator(),
        ),
      );
    }else{
      return Scaffold(
        appBar: AppBar(
          title: const Text(
            "Register as Admin",
            style: TextStyle(
                color: Colors.cyan, fontWeight: FontWeight.bold, fontSize: 24),
          ),
        ),
        body: Container(
          margin: const EdgeInsets.all(16),
          color: Colors.cyan,
          child: Center(
            child: SingleChildScrollView(
              child: Container(
                padding: EdgeInsets.all(8),
                child: Column(
                  children: [
                    const SizedBox(
                      height: 24,
                    ),
                    Container(
                      padding: EdgeInsets.all(16),
                      child: TextField(
                          controller: _controllerName,
                          decoration: const InputDecoration(
                              hintText: 'Name',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Container(
                      padding: EdgeInsets.all(16),
                      child: TextField(
                          controller: _controlleremail,
                          decoration: const InputDecoration(
                              hintText: 'email id',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Container(
                      padding: EdgeInsets.all(16),
                      child: TextField(
                          controller: _controllerphone,
                          keyboardType: TextInputType.number,
                          decoration: const InputDecoration(
                              hintText: 'phone number',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Container(
                      padding: EdgeInsets.all(16),
                      child: TextField(
                          controller: _controllerpassword,
                          decoration: const InputDecoration(
                              hintText: 'password',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Container(
                      padding: EdgeInsets.all(16),
                      child: TextField(
                          controller: _controllerrepassword,
                          decoration: const InputDecoration(
                              hintText: 'Re enter password',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Container(
                      padding: const EdgeInsets.all(16),
                      child: TextField(
                          controller: _controllerAdminKey,
                          decoration: const InputDecoration(
                              hintText: 'Metamask Private key',
                              border: OutlineInputBorder(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(8))))),
                    ),
                    const SizedBox(
                      height: 24,
                    ),
                    ElevatedButton(
                      onPressed: () async {
                        if (_controllerpassword.text.isNotEmpty && _controlleremail.text.isNotEmpty) {
                          if(_controllerAdminKey.text.isNotEmpty&&_controllerName.text.isNotEmpty){
                            if(_controllerphone.text.isNotEmpty&&_controllerpassword.text==_controllerrepassword.text){
                              await addAndCreateUser();
                            }
                          }
                        }
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.white),
                      child: const Text(
                        'Register as Admin',
                        style: TextStyle(color: Colors.cyan),
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ),
      );

    }
  }
}

问题原因

异常核心是State对象已被dispose后仍调用了setState。当前代码的流程问题:

  1. addAndCreateUser中先设置加载状态,随后调用createUserWithEmailAndPassword
  2. 注册成功后立刻执行Navigator.pushAndRemoveUntil,将当前页面从导航栈中移除,此时_AdminRegisterState已变为unmounted状态
  3. 但后续仍会执行await addUser(),最后调用setState(() { _isloading = false; }),此时State已被dispose,触发异常
  4. 同时createUserWithEmailAndPassword内部在Navigator之后也会执行setState,同样会触发错误

解决方案

1. 调整异步操作顺序,确保Navigator在所有异步任务完成后执行

把页面跳转逻辑移到所有异步操作(注册+添加用户到Firestore)完成之后,避免提前销毁当前State。

2. 所有setState调用前检查mounted状态

确保只有当State仍挂载在Widget树中时才更新状态。

修改后的关键代码片段

// 修改createUserWithEmailAndPassword,返回注册是否成功,移除内部的Navigator和加载状态控制
Future<bool> createUserWithEmailAndPassword() async {
  try {
    await Auth().createUserwithEmailAndPassword(email: _controlleremail.text, password: _controllerpassword.text);
    return true;
  } on FirebaseAuthException catch (e) {
    if (mounted) {
      setState(() {
        errormessage = e.message;
      });
    }
    return false;
  }
}

// 修改addAndCreateUser,统一控制加载状态和流程
Future<void> addAndCreateUser() async {
  if (!mounted) return;
  setState(() { _isloading = true; });
  
  bool isRegistered = await createUserWithEmailAndPassword();
  if (isRegistered) {
    await addUser();
    if (mounted) {
      // 所有异步操作完成后再跳转页面
      Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => AdminHome()),(route) => false);
    }
  }
  
  if (mounted) {
    setState(() { _isloading = false; });
  }
}

额外优化建议

  • 在dispose方法中销毁所有TextEditingController,避免内存泄漏:
@override
void dispose() {
  _controllerName.dispose();
  _controlleremail.dispose();
  _controllerphone.dispose();
  _controllerpassword.dispose();
  _controllerrepassword.dispose();
  _controllerAdminKey.dispose();
  super.dispose();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:20:52