I get the counter integer from the Navigator.of arguments and display it on the appBar. It works fine but I have a decrement button that should decrement the counter by 1 each time it is fired but the UI isn`t updating ever after setState is called.

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final routeArgs = ModalRoute.of(context).settings.arguments as Map<String, String>;
    int count;
    String title;
    if(routeArgs == null){
      count = 1;
      title = 'Title';
    }
    else {
      count = int.parse(routeArgs['count']);
      title = routeArgs['title'];
    }
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.arrow_back_ios),
                onPressed: (){
                  setState(() {
                    count -= 1; //calling setState to decrease count by 1
                  });
                },
              ),
              InkWell(
                child: Container(
                  child: Text(title),
                ),
                onTap: ()=>Navigator.of(context).pushNamed('/choice'),
              ),
              Container(
                  child: Text(count.toString()), //This is not updating after setState called.
                ),
              IconButton(
                icon: Icon(Icons.arrow_forward_ios),
                onPressed: () {},
              ),
            ],
          ),
        ),
        drawer: Drawer(),
      );
  }
}


Solution 1: dlohani

I think the problem is you have declared int count inside build method. That re initializes the count variable every time you call setState so its not working. Try moving it outside build method as follows

class _MyHomePageState extends State<MyHomePage> {
  int count; //this is moved outside of build function
  @override
  Widget build(BuildContext context) {
    final routeArgs = ModalRoute.of(context).settings.arguments as Map<String, String>;
    String title;
    if(routeArgs == null){
      count = count?? 1;
      title = 'Title';
    }
    else {
      count = count?? int.parse(routeArgs['count']);
      title = routeArgs['title'];
    }
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.arrow_back_ios),
                onPressed: (){
                  setState(() {
                    count -= 1; //calling setState to decrease count by 1
                  });
                },
              ),
              InkWell(
                child: Container(
                  child: Text(title),
                ),
                onTap: ()=>Navigator.of(context).pushNamed('/choice'),
              ),
              Container(
                  child: Text(count.toString()), //This is not updating after setState called.
                ),
              IconButton(
                icon: Icon(Icons.arrow_forward_ios),
                onPressed: () {},
              ),
            ],
          ),
        ),
        drawer: Drawer(),
      );
  }
}


Solution 2: Yudhishthir Singh

If you put state variables in the build functions then they are initialised every time the build function runs, which is pretty frequent. You should always define state variables outside the build method and inside the class, so that the build function's re-running doesn't affect the current value that the state variable holds.


Solution 3: Broding Camel

You must set your count variable with 0 value like below code:

int count = 0;


Solution 4: Crazy Lazy Cat

Try this

class _MyHomePageState extends State<MyHomePage> {
  int count = 1;
  String title = 'Title';

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback(_initializeFromArgs);
    super.initState();
  }

  void _initializeFromArgs(_) {
    final routeArgs =
        ModalRoute.of(context).settings.arguments as Map<String, String>;
    if (routeArgs != null) {
      count = int.parse(routeArgs['count']);
      title = routeArgs['title'];
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            IconButton(
              icon: Icon(Icons.arrow_back_ios),
              onPressed: () {
                setState(() {
                  count -= 1;
                });
              },
            ),
            InkWell(
              child: Container(
                child: Text(title),
              ),
              onTap: () => Navigator.of(context).pushNamed('/choice'),
            ),
            Container(
              child: Text(count.toString()),
            ),
            IconButton(
              icon: Icon(Icons.arrow_forward_ios),
              onPressed: () {},
            ),
          ],
        ),
      ),
      drawer: Drawer(),
    );
  }
}