颤振错误:此小部件已卸载,因此状态不再具有上下文(应视为已失效)

Posted

技术标签:

【中文标题】颤振错误:此小部件已卸载,因此状态不再具有上下文(应视为已失效)【英文标题】:flutter error: This widget has been unmounted, so the State no longer has a context (and should be considered defunct) 【发布时间】:2021-09-16 05:32:40 【问题描述】:

当我点击登录按钮时我的手机号码错误然后打开一个错误对话框,然后当我点击对话框上的 okey 时出现此错误。

我收到了这条消息

此小部件已卸载,因此 State 不再具有上下文 (并且应该被认为是不复存在的)

考虑在“处置”或使用 "mounted" getter 以确定状态是否仍然处于活动状态。

class _LoginPageState extends State<LoginPage> 
  final GlobalKey<FormState> _formKey = GlobalKey();

  TextEditingController _mobileController = new TextEditingController();
  // TextEditingController _nameController = new TextEditingController();
  // TextEditingController _emailController = new TextEditingController();
  TextEditingController _passwordController = new TextEditingController();

  Map<String, String> _authData = 
    'user_name': '',
    'user_email': '',
    'username': '',
    'password': ''
  ;

  Future _submit() async 
    print('aa' + _authData['username']);
    if (!_formKey.currentState.validate()) 
   

      return;
    
    _formKey.currentState.save();
    try 
      await Provider.of<Auth>(context, listen: false).login(
          _authData['user_name'],
          _authData['user_email'],
          _authData['username'],
          _authData['password']);


      print('authData_username' + _authData['username']);
      print('authData_password' + _authData['password']);
     on HttpException catch (e) 
      //  catch (e) 
      var errorMessage = 'Authentication Failed';
      if (e.toString().contains('Entered wrong mobile number!')) 
        errorMessage = 'Entered wrong mobile number!';
        print(errorMessage);
        _showerrorDialog(errorMessage);
       else if (e.toString().contains('Entered wrong password!')) 
        errorMessage = 'Entered wrong password!';
        _showerrorDialog(errorMessage);
      
     catch (error) 
      var errorMessage = 'Please try again later';
      _showerrorDialog(errorMessage);
    
  

  @override
  void dispose() 
    // TODO: implement dispose
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Container(
        child: ListView(
          children: <Widget>[
            Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height / 3.5,
              decoration: BoxDecoration(
                  gradient: LinearGradient(
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                      
                      colors: myGradient2),
                  borderRadius:
                      BorderRadius.only(bottomLeft: Radius.circular(90))),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Spacer(),
                  Align(
                    alignment: Alignment.center,
                    child: Icon(
                      Icons.person,
                      size: 90,
                      color: kWhite,
                    ),
                  ),
                  Spacer(),
                  Align(
                    alignment: Alignment.bottomRight,
                    child: Padding(
                      padding: const EdgeInsets.only(bottom: 32, right: 32),
                      child: Text(
                        'Login',
                        style: TextStyle(color: kWhite, fontSize: 18),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Container(
              height: MediaQuery.of(context).size.height / 2,
              width: MediaQuery.of(context).size.width,
              padding: EdgeInsets.only(top: 62),
              child: Form(
                key: _formKey,
                child: Column(
                  children: <Widget>[
                    Container(
                      width: MediaQuery.of(context).size.width / 1.2,
                      // height: 45,
                      child: TextFormField(
                        keyboardType: TextInputType.name,
                        autofocus: false,
                        decoration: InputDecoration(
                          hintText: 'Username.',
                          contentPadding:
                              EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
                          border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(32.0)),
                        ),
                        validator: (input) =>
                            input.length > 10 || input.length < 10
                                ? "Mobile Number should be valid"
                                : null,
                        controller: _mobileController,
                        onSaved: (value) 
                          _authData['username'] = value;
                        ,
                        // maxLength: 10,
                      ),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    Container(
                      width: MediaQuery.of(context).size.width / 1.2,
                      // height: 45,
                      child: TextFormField(
                        keyboardType: TextInputType.text,
                        autofocus: false,
                        obscureText: true,
                        decoration: InputDecoration(
                          hintText: 'Password',
                          contentPadding:
                              EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
                          border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(32.0)),
                        ),
                        validator: (input) => input.length < 3
                            ? "Password should be more than 3 characters"
                            : null,
                        controller: _passwordController,
                        onSaved: (value) 
                          _authData['password'] = value;
                        ,
                      ),
                    ),
                    Align(
                      alignment: Alignment.centerRight,
                      child: Padding(
                        padding: const EdgeInsets.only(top: 16, right: 32),
                        child: Text(
                          'Forgot Password ?',
                          style: TextStyle(color: Colors.grey),
                        ),
                      ),
                    ),
                    Spacer(),
                    InkWell(
                      onTap: () 
                        _submit();
                      ,
                      child: Container(
                        height: 45,
                        width: MediaQuery.of(context).size.width / 1.2,
                        decoration: BoxDecoration(
                            gradient: LinearGradient(
                              colors: myGradient2,
                            ),
                            borderRadius:
                                BorderRadius.all(Radius.circular(50))),
                        child: Center(
                          child: Text(
                            'Login'.toUpperCase(),
                            style: TextStyle(
                                color: Colors.white,
                                fontWeight: FontWeight.bold),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(
              height: 50,
            ),
            InkWell(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text("Dnon't have an account ?"),
                  Text(
                    "Sign Up",
                    style: TextStyle(color: kGreen),
                  ),
                ],
              ),
              onTap: () 
                // Navigator.pushNamed(context, '/signup');
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SignupPage()),
                );
              ,
            ),
          ],
        ),
      ),
    );
  

  void _showerrorDialog(String message) 
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: Text(
          'An Error Occurs',
          style: TextStyle(color: Colors.blue),
        ),
        content: Text(message),
        actions: <Widget>[
          FlatButton(
              child: Text('Okay'), onPressed: () => Navigator.of(mounted).pop())
        ],
      ),
    );
  


【问题讨论】:

【参考方案1】:

这是因为您没有处置或取消任何订阅或控制器。TRr 处置或取消订阅或控制器。

【讨论】:

【参考方案2】:

此小部件已被卸载,因此 State 不再具有上下文(应视为已失效)。考虑取消任何。 答:

if (mounted) 
  ...

【讨论】:

【参考方案3】:

尝试使用

Navigator.pop() 或 Navigator.of(context, rootNavigator: true).pop()

而不是 Navigator.of(mounted).pop()) 来关闭 Dialog 窗口。

【讨论】:

以上是关于颤振错误:此小部件已卸载,因此状态不再具有上下文(应视为已失效)的主要内容,如果未能解决你的问题,请参考以下文章

错误:在此小部件上方找不到正确的提供程序 <List<Auftrag>>

颤振有状态的小部件在热重载和 pushNamed 之后丢失数据

颤振小部件中的可见性没有改变

Flutter:错误是查找已停用小部件的祖先是不安全的

颤振步进器小部件 - 在各个步骤中验证字段

无状态颤振小部件中的非最终字段