Home > Software engineering >  How to setState does work in my flutter code?
How to setState does work in my flutter code?

Time:08-21

enter image description here

enter image description here

In onpressed(), print works. "addUpToFirst() executed in 0:00:00.047199" I expected duration value should be changed to 0:00:00.047199. in layout. but it isn't. still 0. I don't know why setState change duration value in layout. I need help. Thank you.

CodePudding user response:

You're not using any state variable.

In a StatefulWidget you usually have some class properties (or variables), whereas you're declaring everything inside your build method. Here's the problem. You should move that variable outside the build method and make it a class property.

You always had 0 in your layout because, even though you correctly invoke and use setState to update duration, every time setState is called, by definition the build method is re-run and therefore you re-initialize duration to zero in the next rebuild.

This is why the print statement worked (it's in the button callback and executes in its own scope) while the layout didn't.

Code (I didn't test it):

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var duration = Duration(microseconds: 0);  // This is the only change!
  
  @override
  Widget build(BuildContext context) {
    String str_addUpToFirst = '''
    int addUpToFirst(n) {
      var total = 0;
      for (var i = 0; i <= n; i  ) {
        total  = i;
      }
      return total;
    }
    ''';
    int addUpToFirst(n) {
      var total = 0;
      for (var i = 0; i <= n; i  ) {
        total  = i;
      }
      return total;
    }

    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Container(
              width: double.infinity,
              color: Colors.blue,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text("Performance Tracker"),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                        onPressed: () {
                          setState(() {
                            Stopwatch stopwatch = new Stopwatch()..start();
                            addUpToFirst(10000000);
                            duration = stopwatch.elapsed;
                          });
                          print('addUpToFirst() executed in ${duration}');
                        },
                        child: Text("addUpToFirst"),
                      ),
                      ElevatedButton(
                        onPressed: () {},
                        child: Text("addUpToSecond"),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Container(
                          decoration: BoxDecoration(),
                          width: 50,
                          child: TextField()),
                      ElevatedButton(
                        onPressed: () {},
                        child: Text('Plot!'),
                      ),
                    ],
                  )
                ],
              ),
            ),
            flex: 1,
          ),
          Expanded(
            child: Container(
              // color: Colors.black,
              child: Row(
                children: [
                  Expanded(
                    child: Container(
                      color: Colors.grey,
                      child: Padding(
                        padding: EdgeInsets.only(top: 20),
                        child: Align(
                          alignment: Alignment.topCenter,
                          child: LayoutBuilder(
                            builder: (context, constraints) {
                              return Container(
                                color: Colors.yellow[100],
                                width: constraints.maxWidth * 0.9,
                                height: constraints.maxHeight * 0.5,
                                child: Text(str_addUpToFirst),
                              );
                            },
                          ),
                        ),
                      ),
                    ),
                  ),
                  Expanded(
                    child: Container(
                      color: Colors.white,
                      child: Text('$duration'),
                    ),
                  ),
                ],
              ),
            ),
            flex: 2,
          ),
        ],
      ),
    );
  }
}

CodePudding user response:

When you call the setState method, the build method is called again. So the value that needs to be changed remains the same.

So instead of declaring variables inside the build method, you need to call variables outside the build method.

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Duration duration = const Duration(microseconds: 0);

  String str_addUpToFirst = '''
    int addUpToFirst(n) {
      var total = 0;
      for (var i = 0; i <= n; i  ) {
        total  = i;
      }
      return total;
    }
    ''';
  int addUpToFirst(n) {
    var total = 0;
    for (var i = 0; i <= n; i  ) {
      total  = i;
    }
    return total;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: Container(
              width: double.infinity,
              color: Colors.blue,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text("Performance Tracker"),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                        onPressed: () {
                          setState(() {
                            Stopwatch stopwatch = new Stopwatch()..start();
                            addUpToFirst(10000000);
                            duration = stopwatch.elapsed;
                          });
                          print('addUpToFirst() executed in ${duration}');
                        },
                        child: const Text("addUpToFirst"),
                      ),
                      ElevatedButton(
                        onPressed: () {},
                        child: const Text("addUpToSecond"),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Container(
                          decoration: const BoxDecoration(),
                          width: 50,
                          child: const TextField()),
                      ElevatedButton(
                        onPressed: () {},
                        child: const Text('Plot!'),
                      ),
                    ],
                  )
                ],
              ),
            ),
            flex: 1,
          ),
          Expanded(
            child: Container(
              // color: Colors.black,
              child: Row(
                children: [
                  Expanded(
                    child: Container(
                      color: Colors.grey,
                      child: Padding(
                        padding: const EdgeInsets.only(top: 20),
                        child: Align(
                          alignment: Alignment.topCenter,
                          child: LayoutBuilder(
                            builder: (context, constraints) {
                              return Container(
                                color: Colors.yellow[100],
                                width: constraints.maxWidth * 0.9,
                                height: constraints.maxHeight * 0.5,
                                child: Text(str_addUpToFirst),
                              );
                            },
                          ),
                        ),
                      ),
                    ),
                  ),
                  Expanded(
                    child: Container(
                      color: Colors.white,
                      child: Text('$duration'),
                    ),
                  ),
                ],
              ),
            ),
            flex: 2,
          ),
        ],
      ),
    );
  }
}
  • Related