Search code examples
httpflutterdartsetstateprovider

Flutter : i got an error that State object for a widget that no longer appears in the widget tree


  • when i try to press on the send button to do the http request[which is done successflly] i got the below error, how can i solve it?!!

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: setState() called after dispose(): _ForgetPasswordDialogState#95548(lifecycle state: defunct, not mounted



import 'dart:io';

import 'package:Zabatnee/common_app/provider/user_details_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class ForgetPasswordDialog extends StatefulWidget {
  static const routeName = '/customeDialog';
  final String title,description;
  

  ForgetPasswordDialog({
    this.title, 
    this.description,});

  @override
  _ForgetPasswordDialogState createState() => _ForgetPasswordDialogState();
}

class _ForgetPasswordDialogState extends State<ForgetPasswordDialog> {
final emailController = TextEditingController();
  var _isLoading = false;

_showDialog(String title, String message) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (ctx) => WillPopScope(
        onWillPop: () async => false,
        child: new AlertDialog(
          elevation: 15,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.all(Radius.circular(8))),
          title: Text(
            title,
            style: TextStyle(color: Colors.white),
          ),
          content: Text(
            message,
            style: TextStyle(color: Colors.white),
          ),
          backgroundColor: Theme.of(context).primaryColor,
          actions: <Widget>[
            FlatButton(
              child: Text(
                'OK',
                style: TextStyle(color: Theme.of(context).accentColor),
              ),
              onPressed: () {
                Navigator.of(context).pop();
                setState(
                  () {
                    _isLoading = false;
                  },
                );
              },
            )
          ],
        ),
      ),
    );
  }



  Future<void> _forgetPassword (String email) async {

    try{
     setState(() {
       _isLoading = true;
     }); 
    await Provider.of<UserDetailsProvider>(context, listen: false).forgetPassword(email);
      print('code are sent via email');
    } on HttpException catch (error) {
      _showDialog('Authentication Failed', error.message);
    } on SocketException catch (_) {
      _showDialog('An error occured',
          'please check your internet connection and try again later');
    } catch (error) {
      _showDialog('Authentication Failed',
          'Something went wrong, please try again later');
    }
    setState(() {
      _isLoading = false;
    });
  }
  @override
  void dispose() {
    emailController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Dialog(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(16)
      ),
      elevation: 8,
      backgroundColor: Theme.of(context).accentColor,
      child: dialogContent(context),
    );
  }

  dialogContent(BuildContext context){
    

    return Container(
      padding: EdgeInsets.only(
        top: 50,
        right: 16,
        left: 16,
        bottom: 16,
      ),
      margin: EdgeInsets.all(8),
      width: double.infinity,
      decoration: BoxDecoration(
        color: Theme.of(context).accentColor,
        shape: BoxShape.rectangle,
        borderRadius: BorderRadius.circular(17),
        boxShadow: [
          BoxShadow(
            color: Colors.black87,
            blurRadius: 10.0,
            offset: Offset(0.0,10.0),
          )
        ]
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            widget.title,
            style: TextStyle(
              fontSize: 24,
            ),
            ),
          SizedBox(
            height: 20,
          ),
          Text(widget.description, style: TextStyle(fontSize: 16),
          ),
          SizedBox(
            height: 20,
          ),
          TextField(
            controller: emailController,
            style: TextStyle(color: Colors.white),
            keyboardType: TextInputType.emailAddress,
            decoration: InputDecoration(
              border: OutlineInputBorder(
                borderSide: BorderSide(color:Theme.of(context).primaryColor)
              ),
              fillColor: Colors.black87,
              hintStyle: TextStyle(color:Colors.grey),
              hintText: 'please enter your email',
              labelText: 'Email',
              labelStyle: TextStyle(color:Colors.white)
            ),  
          ),
          SizedBox(
            height: 20,
          ),
          Container(
            width: double.infinity,
            child: RaisedButton(
              child: Text('Send'),
              onPressed: (){
                _isLoading 
                ? CircularProgressIndicator()
                : print(emailController.text);
                _forgetPassword(emailController.text);
                Navigator.of(context).pop();
              }
              ),
          ),
          Container(
            width: double.infinity,
            child: RaisedButton(
              child: Text('Cancel'),
              onPressed: (){
                Navigator.of(context).pop();
              }
              ),
          ),  
        ],
      ),
    );
  }
}

Solution

  • Replace your

    setState((){});

    with

    if (mounted) setState(() {});.

    The mounted checks Whether the [State] object is currently in a tree. That way, you would be able to avoid the error.