'TextEditingController previous state is not getting disposed in Flutter

I am using my own custom TextEditingController to add text to a TextField. I am disposing the TextEditingController in the dispose() method. Problem is when I enter some text in the TextField and just go back to previous screen and again come back. The text remains in the TextField which I don't want it to happen. I want to get it cleared as soon as the screen is popped off from the stack. How can I solve this?

class AddGoalsState extends State<AddGoalScreen> {
  GoalsBloc _bloc;
  TextEditingController myController = TextEditingController();

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _bloc = GoalsBlocProvider.of(context);
  }

  @override
  void dispose() {
    myController.dispose();
    _bloc.dispose();
    super.dispose();
  }
  Future<bool> _onWillPop(){
    Navigator.pop(context, false);
    return Future.value(false);
  }
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            "Add Goal",
            style: TextStyle(color: Colors.black),
          ),
          backgroundColor: Colors.amber,
          elevation: 0.0,
        ),
        body: Container(
          padding: EdgeInsets.all(16.0),
          alignment: Alignment(0.0, 0.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              nameField(),
              Container(margin: EdgeInsets.only(top: 5.0, bottom: 5.0)),
              goalField(),
              Container(margin: EdgeInsets.only(top: 5.0, bottom: 5.0)),
              buttons(),
            ],
          ),
        ),
      ),
    );
  }

  Widget goalField() {
    return StreamBuilder(
        stream: _bloc.goalMessage,
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          myController.value = myController.value.copyWith(text: snapshot.data);
          return TextField(
            controller: myController,
            keyboardType: TextInputType.multiline,
            maxLines: 3,
            onChanged: _bloc.changeGoalMessage,
            decoration: InputDecoration(
                hintText: "Enter your goal here", errorText: snapshot.error),
          );
        });
  }

My BLoC class:

class GoalsBloc {
  final _repository = Repository();
  final _title = BehaviorSubject<String>();
  final _goalMessage = BehaviorSubject<String>();
  final _showProgress = BehaviorSubject<bool>();

  Observable<String> get name => _title.stream.transform(_validateName);

  Observable<String> get goalMessage =>
      _goalMessage.stream.transform(_validateMessage);

  Observable<bool> get showProgress => _showProgress.stream;

  Function(String) get changeName => _title.sink.add;

  Function(String) get changeGoalMessage => _goalMessage.sink.add;

  final _validateMessage = StreamTransformer<String, String>.fromHandlers(
      handleData: (goalMessage, sink) {
    if (goalMessage.length > 10) {
      sink.add(goalMessage);
    } else {
      sink.addError(StringConstant.goalValidateMessage);
    }
  });

  final _validateName = StreamTransformer<String, String>.fromHandlers(
      handleData: (String name, sink) {
    if (RegExp(r'[!@#<>?":_`~;[\]\\|=+)(*&^%0-9-]').hasMatch(name)) {
      sink.addError(StringConstant.nameValidateMessage);
    } else {
      sink.add(name);
    }
  });

  void submit(String email) {
    _showProgress.sink.add(true);
    _repository
        .uploadGoal(email, _title.value, _goalMessage.value)
        .then((value) {
      _showProgress.sink.add(false);
    });
  }

  void extractText(var image) {
    _repository.extractText(image).then((text) {
      _goalMessage.sink.add(text);
    });
  }

  Stream<DocumentSnapshot> myGoalsList(String email) {
    return _repository.myGoalList(email);
  }

  Stream<QuerySnapshot> othersGoalList() {
    return _repository.othersGoalList();
  }

  //dispose all open sink
  void dispose() async {
    await _goalMessage.drain();
    _goalMessage.close();
    await _title.drain();
    _title.close();
    await _showProgress.drain();
    _showProgress.close();
  }

  //Convert map to goal list
  List mapToList({DocumentSnapshot doc, List<DocumentSnapshot> docList}) {
    if (docList != null) {
      List<OtherGoal> goalList = [];
      docList.forEach((document) {
        String email = document.data[StringConstant.emailField];
        Map<String, String> goals =
            document.data[StringConstant.goalField] != null
                ? document.data[StringConstant.goalField].cast<String, String>()
                : null;
        if (goals != null) {
          goals.forEach((title, message) {
            OtherGoal otherGoal = OtherGoal(email, title, message);
            goalList.add(otherGoal);
          });
        }
      });
      return goalList;
    } else {
      Map<String, String> goals = doc.data[StringConstant.goalField] != null
          ? doc.data[StringConstant.goalField].cast<String, String>()
          : null;
      List<Goal> goalList = [];
      if (goals != null) {
        goals.forEach((title, message) {
          Goal goal = Goal(title, message);
          goalList.add(goal);
        });
      }
      return goalList;
    }
  }

  //Remove item from the goal list
  void removeGoal(String title, String email) {
    return _repository.removeGoal(title, email);
  }
}


Solution 1:[1]

You can simply use the clear() method

controller.clear();

Define it in a dispose() method.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeremy Caney