skip to Main Content

I have got a State Management Problem I couldn’t get rid of and I want to reach out to you.

Basically, I activate with the Buttons a game and I am sending a String to the uC. The uC does its stuff and sends a response to Flutter including gameFinished=true (that works).

Now I want to reset the State of the Button to the init state WITHOUT pressing the Button. Following are some things I tried that didn’t work.

@override
  void initState() {
    super.initState();
    setState(() {
      gameAktivated = false;
      gameStarted = false;
    });
  }
void asyncSetState() async {
    setState(() async {
      gameAktivated = false;
      gameStarted = false;
    });
  }

I am changing the style from "Start" to "Stop" when the Button is pressed and I send Data to the uC. (Works)
Edit: Ofc I have a second button that triggers gameAktivated=true 🙂

ElevatedButton(
 onPressed: () {
  if (gameAktivated) {
   setState(() {
   gameStarted = !gameStarted;
  });
 if (gameStarted) {
  //Send Data to uC
 } else if (!gameStarted) {
  //Send Data to uC
 }
}
},
                    
child:
!gameStarted ? const Text('Start') : const Text('Stop'),
),

Button Displays Stop now.
Following I am receiving a String from the uC that I jsonEncode and I receive gameFinished=true. (Works)

Container(
 child: streamInit
 ? StreamBuilder<List<int>>(
  stream: stream,
  builder: (BuildContext context,
  AsyncSnapshot<List<int>> snapshot) {
   if (snapshot.hasError) {
    return Text('Error: ${snapshot.error}');
   }
   if (snapshot.connectionState ==ConnectionState.active) {
    // getting data from Bluetooth
    var currentValue =const BluetoothConnection().dataParser(snapshot.data);
    config.jsonDeserializeGameFinished(currentValue);
    if(config.gameFinished){
     setState(() {
      gameAktivated = false;
      gameStarted = false;
     });
     asyncSetState();//Tested both methods seperate!
    }
    return Column(
     children: [
      Text(config.time.toString()),
     ],
    );
   } else {
    return const Text(
    'Check the stream',
    textAlign: TextAlign.center,
   );
  }
},
 ): const Text("NaN",textAlign: TextAlign.center,),
),

When I try to reset the state like in the code above this error occures: enter image description here

Calling setState Async didnt work for me either.
Where and how can I set the state based on the response from the uC?
Is it possible without using Provider Lib?
Thanks in advance Manuel.

3

Answers


  1. Chosen as BEST ANSWER

    Answer to my own Question: In initState() added this:

    stream.listen((event) {
     String valueJSON = const BluetoothConnection().dataParser(event);
     config.jsonDeserializeGameFinished(valueJSON);
     if (config.gameFinished) {
      setState(() {
       gameAktivated = false;
       gameStarted = false;
      });
     }
    });
    

    The Code above listens to the stream, UTF-8 Decodes and JSON-Decodes the data. After this you can access the variable to set a state.


  2. If you want to call setState() immediately after the build method was called you should use:

     WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
         // this method gets called once directly after the previous setState() finishes.
     });
    
    Login or Signup to reply.
  3. Actually this error is not about the changing the state of button. Its a common mistake to update the widget state when its still building the widget tree.

    Inside your StreamBuilder, you are trying to update the state before creating the UI which is raising this issue.

    if(config.gameFinished){
         setState(() {
          gameAktivated = false;
          gameStarted = false;
         });
    

    This will interrupt the build process of StreamBuilder as it will start updating the whole page. You need to move it out of the StreamBuilder’s builder method.

    To do that simply convert your stream to a broadcast, which will allow you to listen your stream multiple time.

    var controller = StreamController<String>.broadcast();
    

    Then inside the initState of the page you can setup a listener method to listen the changes like this

     stream.listen((val) => setState((){
          number = val;
        }));
    

    Here you can change the state values because from here it will not interrupt the widget tree building cycle.

    For more details see this example I created
    https://dartpad.dev/?id=a7986c44180ef0cb6555405ec25b482d

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search