How to change a boolean inside a widget listview.builder and pass it to another widget?

Solution for How to change a boolean inside a widget listview.builder and pass it to another widget?
is Given Below:

I am currently developing an application on Android Studio in order to turn on and off a truck. The application will be a client to our server TCP that will send data on the truck.

I have a problem while implementing the history of the truck’s state. Right now, I am able to display the received data on the history.
However, we want the play and stop buttons of the truck to be unclickable while the server has not released them with an “unlocked” message.
I start to implement this with a boolean variable call isButtonClickable initialize to true.

I have insert a condition into the OnPressed{} of each buttons.
So, I am encountering a problem when I am trying to parse the message and I want to see if it equals to “Lock” or “Unlock” to change the state of the boolean variable.

I tried to test incoming message when I am reading and displaying them in my Listview.Builder but I a get an error message because it is impossible to use SetState() while the application is building the widget.

Here is what my screen look like at the moment:

enter image description here

enter image description here

Here is what I am trying to do :

import 'package:bubble/bubble.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:untitled/truck_icons.dart';
import '../models/message.dart';
import '../utils/validators.dart';
import '../tcp_bloc/tcp_bloc.dart';
import 'about_page.dart';

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  TcpBloc? _tcpBloc;
  TextEditingController? _hostEditingController;
  TextEditingController? _portEditingController;
  TextEditingController? _chatTextEditingController;

  bool isButtonClickable=true;
  void ButtonUnclickable(){
    setState(() {
      isButtonClickable=false;
    });
  }
  void ButtonClickable(){
    setState(() {
      isButtonClickable=true;
    });
  }

  void TestMessage(TcpState tcpState,int idx){
    Message m = tcpState.messages[idx];
    if(m.message=="Unlock"){
      ButtonClickable();
    }else{
      ButtonUnclickable();
    }
  }

  @override
  void initState() {
    super.initState();
    _tcpBloc =  BlocProvider.of<TcpBloc>(context);

//Default parameter of my TCP server
    _hostEditingController = new TextEditingController(text: '192.168.1.28');
    _portEditingController = new TextEditingController(text: '9632');
    _chatTextEditingController = new TextEditingController(text: '');

    _chatTextEditingController!.addListener(() {
      setState(() {

      });
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('Truck Application')
      ),
      body: BlocConsumer<TcpBloc, TcpState>(
        bloc: _tcpBloc,
        listener: (BuildContext context, TcpState tcpState) {
          if (tcpState.connectionState == SocketConnectionState.Connected) {
            ScaffoldMessenger.of(context)
              ..hideCurrentSnackBar();
          } else if (tcpState.connectionState == SocketConnectionState.Failed) {
            ScaffoldMessenger.of(context)
              ..hideCurrentSnackBar()
              ..showSnackBar(
                SnackBar(
                  content: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [Text("Connection failed"), Icon(Icons.error)],
                  ),
                  backgroundColor: Colors.red,
                ),
              );
          }
        },
        builder: (context, tcpState) {
          if (tcpState.connectionState == SocketConnectionState.None || tcpState.connectionState == SocketConnectionState.Failed) {
            return Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8.0),
//Checking IP/port TCP serveur
              child: ListView(
                children: [
                  TextFormField(
                    controller: _hostEditingController,
                    autovalidateMode : AutovalidateMode.always,
                    validator: (str) => isValidHost(str) ? null : 'Invalid hostname',
                    decoration: InputDecoration(
                      helperText: 'The ip address or hostname of the TCP server',
                      hintText: 'Enter the address here, e. g. 10.0.2.2',
                    ),
                  ),
                  TextFormField(
                    controller: _portEditingController,
                    autovalidateMode : AutovalidateMode.always,
                    validator: (str) => isValidPort(str) ? null : 'Invalid port',
                    decoration: InputDecoration(
                      helperText: 'The port the TCP server is listening on',
                      hintText: 'Enter the port here, e. g. 8000',
                    ),
                  ),
                  ElevatedButton(
//Checking host and port before connection attempt
                    child: Text('Connect'),
                    onPressed: isValidHost(_hostEditingController!.text) && isValidPort(_portEditingController!.text)
                      ? () {
                        _tcpBloc!.add(
                          Connect(
                            host: _hostEditingController!.text,
                            port: int.parse(_portEditingController!.text)
                          )
                        );
                      }
                      : null,
                  )
                ],
              ),
            );
          } else if (tcpState.connectionState == SocketConnectionState.Connecting) {
//Connection attempt with abort button
            return Center(
              child: Column(
                children: <Widget>[
                  CircularProgressIndicator(),
                  Text('Connecting...'),
                  ElevatedButton(
                    child: Text('Abort'),
                    onPressed: () {
                      _tcpBloc!.add(Disconnect());
                    },
                  )
                ],
              ),
            );
          } else if (tcpState.connectionState == SocketConnectionState.Connected) {
// Connection OK --> Screen Play and Stop truck
            return Column(
              children: [
                Expanded(
                  child: Container(
                    padding: EdgeInsets.all(10),
                    margin: EdgeInsets.fromLTRB(20, 10, 20, 10),
                    //1 ligne
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
//Play button
                        Container(
                          child: Column(
                            children: [
                              Opacity(
                                opacity: isButtonClickable? 1.0:0.2,
                                //padding: EdgeInsets.all(5),
                                child: RaisedButton(
                                  padding: EdgeInsetsDirectional.all(10),
                                  onPressed: () {
                                    if (isButtonClickable){
                                      _tcpBloc!.add(SendMessage(message: '1'));
                                    }
                                  },
                                  color: Colors.green,
                                  child: Icon(
                                    Icons.play_arrow_sharp,
                                    color: Colors.white,
                                    size: 30,
                                  ),
                                ),
                              ),
                              SizedBox(height: 5),
                              Text('Play')
                            ],
                          ),
                        ),
//Stop Buttton
                        Container(
                          child: Column(
                            children: [
                              Opacity(
                                //padding: EdgeInsets.all(5),
                                opacity: isButtonClickable? 1.0:0.2,
                                child: RaisedButton(
                                  padding: EdgeInsetsDirectional.all(10),
                                  onPressed: () {
                                    if(isButtonClickable){
                                      _tcpBloc!.add(SendMessage(message: '0'));
                                    }
                                  },
                                  color: Colors.red,
                                  child: Icon(
                                    Icons.stop,
                                    color: Colors.white,
                                    size: 30,
                                  ),
                                ),
                              ),
                              SizedBox(height: 5),
                              Text('Stop')
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
//Read and display received and requested data
              Container (

                  child: Text("Historique de l'état du camion :",style: TextStyle(color: Colors.white, fontSize: 23)
                  ),
                  decoration: ShapeDecoration(
                    color: Colors.lightBlue,
                    shape: RoundedRectangleBorder (
                    borderRadius: BorderRadius.circular(15.0),
                    side: BorderSide(
                    width: 5,
                    color: Colors.lightBlue),
                  ),
                  ),
                  padding: EdgeInsets.all(3),
                margin: EdgeInsets.fromLTRB(10, 3, 10, 3),
              ),

                Container(
                  height: 460,
                  width : 600,
                  decoration: BoxDecoration(color: Colors.white38,border: Border.all(width: 5,
                    color: Colors.lightBlue,
                  ),),
                  child: ListView.builder(
                      itemCount: tcpState.messages.length,
                      itemBuilder: (context, idx) {
                        Message m = tcpState.messages[idx];
                        return Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Bubble(
                            child:
                            Text(m.message),
                            alignment: m.sender == Sender.Client ? Alignment.centerRight : Alignment.centerLeft,
                          ),
                        );
                      }
                  ),

                ),

//Disconnect Button
                ElevatedButton(
                  child: Text('Disconnect'),
                  onPressed: () {
                    _tcpBloc!.add(Disconnect());
                  },
                ),

              ],
            );
          } else {
            return Container();
          }
        },
      ),
    );
  }
}

Flutter allows to handle your situation, in an easier way: instead of checking if your TCP service is “up” or “not yet up”, you need to await for a Future from your TCP server and build accordingly. Or, if your back end service “shifts” more than once (on<->off), you should subscribe to a Stream to check its value change and build accordingly.

To do so easily, I’d say you should definitively check the FutureBuilder and the StreamBuilder Widgets, which do exactly what you’re asking for.

Here’s the documentation of FutureBuilder.

Here’s the documentation of StreamBuilder.

There is also a quick and enjoyable video in those, so that you can understand its usage, quicker (-: