# setState method

1. @protected

void setState (void fn)

Notify the framework that the internal state of this object has changed.

Whenever you change the internal state of a `State` object, make the change in a function that you pass to setState:

    setState(() { _myState = newValue });

The provided callback is immediately called synchronously. It must not return a future (the callback cannot be `async`), since then it would be unclear when the state was actually being set.

Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface in this subtree, which causes the framework to schedule a build for this `State` object.

If you just change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.

Generally it is recommended that the `setState` method only be used to wrap the actual changes to the state, not any computation that might be associated with the change. For example, here a value used by the build function is incremented, and then the change is written to disk, but only the increment is wrapped in the `setState`:

    Future<Null> _incrementCounter() async {
      setState(() {
        _counter++;
      });
      Directory directory = await getApplicationDocumentsDirectory();
      final String dirName = directory.path;
      await new File('$dir/counter.txt').writeAsString('$_counter');
      return null;
    }

It is an error to call this method after the framework calls dispose. You can determine whether it is legal to call this method by checking whether the mounted property is true.

## Implementation

    @protected
    void setState(VoidCallback fn) {
      assert(fn != null);
      assert(() {
        if (_debugLifecycleState == _StateLifecycle.defunct) {
          throw new FlutterError(
            'setState() called after dispose(): $this\n'
            '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. 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.\n'
            '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().'
          );
        }
        if (_debugLifecycleState == _StateLifecycle.created && !mounted) {
          throw new FlutterError(
            'setState() called in constructor: $this\n'
            'This happens when you call setState() on a State object for a widget that '
            'hasn\'t been inserted into the widget tree yet. It is not necessary to call '
            'setState() in the constructor, since the state is already assumed to be dirty '
            'when it is initially created.'
          );
        }
        return true;
      }());
      final dynamic result = fn() as dynamic;
      assert(() {
        if (result is Future) {
          throw new FlutterError(
            'setState() callback argument returned a Future.\n'
            'The setState() method on $this was called with a closure or method that '
            'returned a Future. Maybe it is marked as "async".\n'
            'Instead of performing asynchronous work inside a call to setState(), first '
            'execute the work (without updating the widget state), and then synchronously '
            'update the state inside a call to setState().'
          );
        }
        // We ignore other types of return values so that you can do things like:
        //   setState(() => x = 3);
        return true;
      }());
      _element.markNeedsBuild();
    }