'TextEditingController stackoverflow error on typing

Here is the minimal reproducible code:

final _controller = TextEditingController();

@override
void initState() {
  super.initState();

  _controller.addListener(() {
    var input = _controller.text;
    _controller.text = input; // A
    _controller.selection = TextSelection.fromPosition(TextPosition(offset: 0)); // B
  });
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(child: TextField(controller: _controller)),
  );
}

As soon as you start typing anything in TextField, you get an stackoverflow error. If you comment out any of the two lines A or B, it works. Not sure what I am doing wrong.

Error:

[VERBOSE-2:ui_dart_state.cc(166)] Unhandled Exception: Stack Overflow
#0      _HashVMBase._data (dart:collection-patch/compact_hash.dart:61:3)
#1      _LinkedHashMapMixin.keys (dart:collection-patch/compact_hash.dart:382:37)
#2      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:373:14)
#3      _JsonStringifier.writeMap (dart:convert/json.dart:753:9)
#4      _JsonStringifier.writeJsonValue (dart:convert/json.dart:723:21)
#5      _JsonStringifier.writeObject (dart:convert/json.dart:678:9)
#6      _JsonStringifier.writeMap (dart:convert/json.dart:768:7)
#7      _JsonStringifier.writeJsonValue (dart:convert/json.dart:723:21)
#8      _JsonStringifier.writeObject (dart:convert/json.dart:678:9)
#9      _JsonStringStringifier.printOn (dart:convert/json.dart:876:17)
#10     _JsonStringStringifier.stringify (dart:convert/json.dart:861:5)
#11     JsonEncoder.convert (dart:convert/json.dart:261:30)
#12     JsonCodec.encode (dart:convert/json.dart:171:45)
#13     JSONMessageCodec.encodeMess<…>


Solution 1:[1]

It is a little bit late but maybe somebody else also faces the same problem like me.

I Solved it by removing the listener, updating the controllers value and adding the listener back again like this:

final _controller = TextEditingController();

void _onChange(){
  var input = _controller.text;
  _controller.removeListener(_onChange);
  _controller.text = input; // A
  _controller.selection = TextSelection.fromPosition(TextPosition(offset: 0)); // B
  _controller.addListener(_onChange);
}

@override
void initState() {
  super.initState();

  _controller.addListener(_onChane);
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(child: TextField(controller: _controller)),
  );
}

Thus, _onChange method can not call itself and cause an infinite loop which was the cause of my error.

Solution 2:[2]

EDIT

The problem is you create a loop when text is change, for example:

  • text changed to "z"
  • listener be notify with value "z"
  • you set controller text with "z"
  • again listener be notify with value "z"

Change your code like this:

final _controller = TextEditingController();


  @override
  void initState() {
    super.initState();
    _controller.addListener(() {
      _controller.selection =
          TextSelection.fromPosition(TextPosition(offset: 0)); // B
    });
  }

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(child: TextField(controller: _controller)),
  );
}

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 Berke Belgin
Solution 2