0

If I remove the awaits from my viewModel.sendMessage() it works as expected, however I can't set the state with the value returned. Is there a way to update the UI from setState?

I'm just not sure how to do both at the same time, the parent class for this widget is a StatefulWidget, Idk if that matters. My ConversationViewModel is just a changeNotifier.

@override
Widget build(BuildContext context) {
  UsViewModel viewModel = Provider.of<UsViewModel>(context, listen: false);
  viewModel.setUs();
  var us = Provider.of<UsViewModel>(context, listen: true).us;
  return Consumer<ConversationViewModel>(builder: (BuildContext context, viewModel, Widget child) {
    return Scaffold(
      key: viewModel.scaffoldKey,
      appBar: AppBar(
        leading: GestureDetector(
          onTap: () {
            Navigator.pop(context);
          },
          child: Icon(
            Icons.keyboard_backspace,
          ),
        ),
        elevation: 0.0,
        titleSpacing: 0,
        title: buildName(),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        child: Column(
          children: [
            Flexible(
              child: StreamBuilder(
                stream: messageListStream(widget.chatId),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    List messages = snapshot.data.docs;
                    return ListView.builder(
                      controller: scrollController,
                      padding: EdgeInsets.symmetric(horizontal: 10.0),
                      itemCount: messages.length,
                      reverse: true,
                      itemBuilder: (BuildContext context, int index) {
                        Message message = Message.fromJson(
                            messages.reversed.toList()[index].data());
                        return ChatBubble(
                            message: '${message.content}',
                            time: message?.time,
                            isMe: message?.senderUid == us?.uid,
                            type: message?.type);
                      },
                    );
                  } else {
                    return Center(child: circularProgress(context));
                  }
                },
              ),
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: BottomAppBar(
                elevation: 10.0,
                child: Container(
                  constraints: BoxConstraints(maxHeight: 100.0),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Flexible(
                        child: TextField(
                          controller: messageController,
                          focusNode: focusNode,
                          style: TextStyle(
                            fontSize: 15.0,
                            color:
                                Theme.of(context).textTheme.headline6.color,
                          ),
                          decoration: InputDecoration(
                            contentPadding: EdgeInsets.all(10.0),
                            enabledBorder: InputBorder.none,
                            border: InputBorder.none,
                            hintText: "Type your message",
                            hintStyle: TextStyle(
                              color:
                                  Theme.of(context).textTheme.headline6.color,
                            ),
                          ),
                          maxLines: null,
                        ),
                      ),
                      IconButton(
                        icon: Icon(
                          Feather.send,
                          color: Theme.of(context).colorScheme.secondary,
                        ),
                        onPressed: () {
                          if (messageController.text.trim().isNotEmpty) {
                            sendMessage(viewModel, us);
                          }
                        },
                      ),
                    ],
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  });
}


sendMessage(ConversationViewModel viewModel, var us,
    {bool isImage = false, int imageType}) async {
  String msg;
  
  msg = messageController.text.trim();
  messageController.clear();

  Message message = Message(
    content: '$msg',
    senderUid: us?.uid,
    time: Timestamp.now(),
  );

  if (msg.isNotEmpty) {
    String id = await viewModel.sendMessage(widget.usId, message);
    setState(() {
      chatId = id;
    });
  }
}
Spider
  • 431
  • 7
  • 21

1 Answers1

0

If you using ChangeNotifier with Provider package you don't need setState method. You should read Provider documentation: https://pub.dev/packages/provider

ft: That you create listeners for each item in this line.

isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,

How to use a provider according to your question, added an example;

@override
Widget build(BuildContext context) {
  context.read<UsViewModel>().setUs();
  return Scaffold(
      key: context.read<UsViewModel>().scaffoldKey,
      appBar: AppBar(
        leading: GestureDetector(
          onTap: () {
            Navigator.pop(context);
          },
          child: Icon(
            Icons.keyboard_backspace,
          ),
        ),
        elevation: 0.0,
        titleSpacing: 0,
        title: buildName(),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        child: Column(
          children: [
            Flexible(
              child: StreamBuilder(
                stream: messageListStream(widget.chatId),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    List messages = snapshot.data.docs;
                    return ListView.builder(
                      controller: scrollController,
                      padding: EdgeInsets.symmetric(horizontal: 10.0),
                      itemCount: messages.length,
                      reverse: true,
                      itemBuilder: (BuildContext context, int index) {
                        Message message = Message.fromJson(
                            messages.reversed.toList()[index].data());
                        return ChatBubble(
                            message: '${message.content}',
                            time: message?.time,
                            isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,
                            type: message?.type);
                      },
                    );
                  } else {
                    return Center(child: circularProgress(context));
                  }
                },
              ),
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: BottomAppBar(
                elevation: 10.0,
                child: Container(
                  constraints: BoxConstraints(maxHeight: 100.0),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Flexible(
                        child: TextField(
                          controller: messageController,
                          focusNode: focusNode,
                          style: TextStyle(
                            fontSize: 15.0,
                            color:
                                Theme.of(context).textTheme.headline6.color,
                          ),
                          decoration: InputDecoration(
                            contentPadding: EdgeInsets.all(10.0),
                            enabledBorder: InputBorder.none,
                            border: InputBorder.none,
                            hintText: "Type your message",
                            hintStyle: TextStyle(
                              color:
                                  Theme.of(context).textTheme.headline6.color,
                            ),
                          ),
                          maxLines: null,
                        ),
                      ),
                      IconButton(
                        icon: Icon(
                          Feather.send,
                          color: Theme.of(context).colorScheme.secondary,
                        ),
                        onPressed: () {
                          if (messageController.text.trim().isNotEmpty) {
                            sendMessage(context);
                          }
                        },
                      ),
                    ],
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
}


sendMessage(BuildContext context) async {
  String msg;
  
  msg = messageController.text.trim();
  messageController.clear();

  Message message = Message(
    content: '$msg',
    senderUid: context.read<UsViewModel>().us?.uid,
    time: Timestamp.now(),
  );

  if (msg.isNotEmpty) {
    String id = await context.read<UsViewModel>().sendMessage(widget.usId, message);
setState((){
chatId = id;
});
  }
}
Salih Can
  • 1,562
  • 1
  • 9
  • 18
  • I missed one line in my sample provided, I'm also setting a member bool to false in the setState, would I keep that in the setState? Also, do I need the local var id? Or should I be assigning it to chatId? – Spider Feb 13 '22 at 23:36
  • Also, I can't use constructor tear offs due to the min sdk version, if I update, it creates around 400 errors, is there another way to write this? – Spider Feb 14 '22 at 00:21
  • I don't know your business logic how it going but you can use setState for the 'chatId'. Updated answer – Salih Can Feb 14 '22 at 06:16
  • Is there a workaround for the constructor tear offs, so I won't have to update to a newer version of the sdk? The first line is causing issues for me – Spider Feb 17 '22 at 12:18