flutterstream-builderstatefulwidgetstatelesswidget

Flutter streambuilder does not update a statefulwidget or statelesswidget


I'm trying to build a streambuilder.
My problem is that the streambuilder does not update other statefulWidgets inside the streambuilder widget.

Here my code:

class ChatPage extends StatefulWidget {
  //pass parm
  var chat_object;
  ChatPage(this.chat_object, {Key? key}) : super(key: key);

  @override
  _ChatPage createState() => _ChatPage();
}

class _ChatPage extends State<ChatPage> {
  //pass parm
  var chat_object;
  _ChatPage(this.chat_object);

  @override
  Widget build(BuildContext context) {
    // Full screen width and height
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;

    // Height (without SafeArea)
    var padding = MediaQuery.of(context).padding;
    double height1 = height - padding.top - padding.bottom;

    // Height (without status bar)
    double height2 = height - padding.top;

    // Height (without status and toolbar)
    double height3 = height - padding.top - kToolbarHeight;

    //scaffold
    return Scaffold(
      appBar: customAppBarGoBack('Chat', context),
      body: LimitedBox(
        maxHeight: height3,
        child: Stack(
          children: [
            StreamBuilder<dynamic>(
              stream: FirebaseFirestore.instance
                  .collection('chat')
                  .doc('chat_messages')
                  .collection(chat_object.chat_message_id[0].trim())
                  .orderBy('message_time')
                  .snapshots(),
              builder: (
                BuildContext context,
                AsyncSnapshot<dynamic> snapshot,
              ) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return CircularProgressIndicator();
                } else {
                  if (snapshot.hasError) {
                    return const Text('Error');
                  } else if (snapshot.hasData) {
                    //chat room object list
                    var chat_room_object =
                        load_object(snapshot.data, chat_object).first;

                    //chat message object list
                    var message_object =
                        load_object(snapshot.data, chat_object).last;

                    print('message_object: ' + message_object.toString());

                    return Test(chat_room_object, message_object);
                  } else {
                    return const Text('Empty data');
                  }
                }
              },
            ),
          ],
        ),
      ),
      drawer: CustomSideBar(context),
    );
  }
}

//test
class Test extends StatefulWidget {
  //pass parm
  var chat_room_object;
  var message_object;
  Test(this.chat_room_object, this.message_object, {Key? key})
      : super(key: key);

  @override
  _Test createState() => _Test(chat_room_object, message_object);
}

class _Test extends State<Test> {
  //pass parm
  _Test(this.chat_room_object, this.message_object);
  var chat_room_object;
  var message_object;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: message_object.length,
      itemBuilder: (context, i) {
        return Text(message_object[i].message.toString());
      },
    );
  }
}

If I build a list inside the streambuilder the list will be update. But if I build the list inside a new widget and pass the values to list the widget will be not update.

Anyone can give me a simple example how I can update the values in a statefulwidget which is contain in a streambuilder?


Solution

  • Instead of passing parameters in the constructor of state of Test widget, can you try to access them directly from the widget.Example as below.

    //test
    class Test extends StatefulWidget {
    //pass parm
    var chat_room_object;
    var message_object;
    
    Test(this.chat_room_object, this.message_object, {Key? key})
      : super(key: key);
    
    @override
    _Test createState() => _Test();
    }
    
    class _Test extends State<Test> {
    //pass parm
    _Test();
    
    @override
    Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: widget.message_object.length,
      itemBuilder: (context, i) {
        return Text(widget.message_object[i].message.toString());
      },
    );
    }
    }