SetState not working with listview.builder

535

Instead of directly using List.add try changing the reference of your messages to a completely new List as well, like this,

messages = [
    ...messages,
    ChatMessage(messageContent: message, messageType: "sender"),
    ChatMessage(messageContent: messageStrings[messageIndex], messageType: "receiver")
];

Why this works is that now, you are destroying the old reference of the messages and assigning it a completely new reference of List.

Share:
535
Archangel
Author by

Archangel

Updated on December 30, 2022

Comments

  • Archangel
    Archangel over 1 year

    i have some code here for a an application chat screen. This specific chat screen is used to chat with a bot. The bot is supposed to send a message after each message by the user. The list of messages to be sent by the bot is stored in messageStrings. I'm using a listview.builder to populate the UI with new messages added in the List messages.

    I'm using setstate to add new messages, but the UI Isn't getting updated with the new messages. This is my code:

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import '../models/chats.dart';
    
    class ReportPage extends StatefulWidget {
      BuildContext context;
      ReportPage(this.context);
      @override
      _ReportPageState createState() => _ReportPageState();
    }
    
    class _ReportPageState extends State<ReportPage> {
      
      @override
      Widget build(Object context) {
        TextEditingController messageContoller = new TextEditingController();
    
        //The first two messages by the bot are already added to the List
        List<ChatMessage> messages = [
        ChatMessage(messageContent: "Message 1", messageType: "receiver"),
        ChatMessage(messageContent: "Message 2", messageType: "receiver"),
      ];
      int messageIndex = 0;
      //The next messages that are to be added to the list after a response from the user
      List<String> messageStrings = ["Message 3", "Message 4","Message 5",];
        return Scaffold(
          appBar: AppBar(
            title: Row(children: [
              Container(
                width: 35,
                height: 35,
                child: Image.asset(
                  'assets/images/police.png',
                  fit: BoxFit.cover,
                ),
                decoration:
                    BoxDecoration(shape: BoxShape.circle, color: Colors.white),
              ),
              SizedBox(
                width: 10,
              ),
              Text("CFB bot"),
            ]),
          ),
          body: Container(
            padding: EdgeInsets.all(20),
            child: Stack(
              children: <Widget>[
                ListView.builder(
                  itemCount: messages.length,
                  shrinkWrap: true,
                  padding: EdgeInsets.only(top: 10, bottom: 10),
                  physics: NeverScrollableScrollPhysics(),
                  itemBuilder: (context, index) {
                    return Container(
                      padding:
                          EdgeInsets.only(left: 14, right: 14, top: 10, bottom: 10),
                      child: Align(
                        alignment: (messages[index].messageType == "receiver"
                            ? Alignment.topLeft
                            : Alignment.topRight),
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            color: (messages[index].messageType == "receiver"
                                ? Colors.grey.shade200
                                : Colors.blue[200]),
                          ),
                          padding: EdgeInsets.all(16),
                          child: Text(
                            messages[index].messageContent,
                            style: TextStyle(fontSize: 15),
                          ),
                        ),
                      ),
                    );
                  },
                ),
                Align(
                  alignment: Alignment.bottomLeft,
                  child: Container(
                    decoration: BoxDecoration(
                        border: Border.all(color: Colors.black),
                        borderRadius: BorderRadius.all(Radius.circular(20))),
                    padding: EdgeInsets.only(left: 10, bottom: 10, top: 10),
                    height: 60,
                    width: double.infinity,
                    child: Row(
                      children: <Widget>[
                        GestureDetector(
                          onTap: () {},
                          child: Container(
                            height: 30,
                            width: 30,
                            decoration: BoxDecoration(
                              color: Colors.lightBlue,
                              borderRadius: BorderRadius.circular(30),
                            ),
                            child: Icon(
                              Icons.add,
                              color: Colors.white,
                              size: 20,
                            ),
                          ),
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        Expanded(
                          child: TextField(
                            decoration: InputDecoration(
                                hintText: "Write message...",
                                hintStyle: TextStyle(color: Colors.black54),
                                border: InputBorder.none),
                                controller: messageContoller,
                          ),
                        ),
                        SizedBox(
                          width: 15,
                        ),
                        FloatingActionButton(
                          onPressed: () {
                            String message = messageContoller.text;
                            setState(() {
                              messages.add(ChatMessage(messageContent: message, messageType: "sender"));              
                              messages.add(ChatMessage(messageContent: messageStrings[messageIndex], messageType: "receiver"));                                        
                            });
                            messageIndex++;
                            for(int i = 0; i < messages.length; i++){
                              print(messages[i].messageContent);
                            }
                          },
                          child: Icon(
                            Icons.send,
                            color: Colors.white,
                            size: 18,
                          ),
                          backgroundColor: Colors.blue,
                          elevation: 0,
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
  • Archangel
    Archangel almost 3 years
    Thanks for the answer. I tried this and it's still not updating the UI. is there any other way i can overcome this issue?
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    That is just not possible.
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    So you are saying, even if you change anything inside your setState, your UI is not rebuilding ?
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    put a print statement inside your build function to check if it is getting called or not.
  • Archangel
    Archangel almost 3 years
    Sorry mate, the issue was that i put the List inside the build function. So, it was getting reset each time. I put it in the State Class and it's working fine now. Thanks for the help
  • Nisanth Reddy
    Nisanth Reddy almost 3 years
    glad to have helped :)