Stream中的Flutter ListView.Builder不会更新

时间:2020-07-04 22:55:21

标签: firebase flutter listview firebase-realtime-database

抱歉,我的英语不好,即时通讯正在使用flutter和firebase实时数据库进行聊天。我正在尝试分页。首先,我加载最后20条聊天消息,并且当用户滚动到聊天顶部时,我想加载20条更多消息。数据已正确恢复,但列表视图未更新。这是我的代码:

class _ChatState extends State<Chat> {
  TextEditingController messageEditingController = new TextEditingController();
  ScrollController _scrollController = ScrollController();
  bool _showKeyboard = true;
  Stream _chats;
  List item = [];

  var _firebaseRef = FirebaseDatabase().reference().child('chatRoom');

  sendMessage() {
    if (messageEditingController.text.isNotEmpty) {
      _firebaseRef.child(widget.chatRoomId).child("chats").push().set({
        "sendBy": widget.user.uid,
        "message": messageEditingController.text,
        "time": DateTime.now().millisecondsSinceEpoch
      });
    }
    setState(() {
      messageEditingController.text = "";
    });
  }

  @override
  void initState() {
    setState(() {
      _chats = _firebaseRef
          .child(widget.chatRoomId)
          .child("chats")
          .limitToLast(20)
          .onValue;
    });

    _scrollController.addListener(() {
      if (_scrollController.position.atEdge) {
        if (_scrollController.position.pixels == 0) {
        } else {
          _requestMoreMessages();
        }
      }
    });

    super.initState();
  }

  _requestMoreMessages() async {

    List _moreItems =[];

    _firebaseRef
        .child(widget.chatRoomId)
        .child("chats")
        .orderByChild("time")
        .endAt(item.elementAt(19)["time"])
        .limitToLast(20)
        .once()
        .then((snapshot) {
      Map<dynamic, dynamic> map = snapshot.value;
      map.forEach((key, data) {

        print(data["message"]);
        _moreItems.add({
          "key": key,
          "message": data['message'],
          "sendBy": data['sendBy'],
          "time": data['time']
        });
      });
      setState(() {
        item.addAll(_moreItems);
      });
    });
  }

  Widget chatMessages() {

    return StreamBuilder(
      stream:_chats,
      builder: (context, snapshot) {
        if (snapshot.hasData &&
            !snapshot.hasError &&
            snapshot.data.snapshot.value != null) {
          Map data = snapshot.data.snapshot.value;
          item = [];
          data.forEach((index, data) => item.add({
                "key": index,
                "message": data['message'],
                "sendBy": data['sendBy'],
                "time": data['time']
              }));
          item.sort((b, a) => a["time"].compareTo(b["time"]));

          return ListView.builder(
              reverse: true,
              controller: _scrollController,
              itemCount: item.length,
              itemBuilder: (context, index) {
                return MessageTile(
                    message: item[index]['message'],
                    sendByMe: widget.user.uid == item[index]['sendBy'],
                    time: item[index]['time']);
              });
        } else {
          return Container();
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: appBarMain(context, widget.userName, widget.urlFoto, context),
        body: Column(
          children: <Widget>[
            Flexible(
              child: chatMessages(),
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: Padding(
                padding: EdgeInsets.all(8),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Container(
                      decoration: BoxDecoration(
                          border: Border.all(color: Colors.black26),
                          borderRadius: BorderRadius.circular(50),
                          color: Colors.black26),
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.center,
                        mainAxisSize: MainAxisSize.max,
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: <Widget>[
                          IconButton(
                            icon: !_showKeyboard == true
                                ? Icon(LineIcons.keyboard_o)
                                : Icon(LineIcons.smile_o),
                            onPressed: () {
                              if (MediaQuery.of(context).viewInsets.bottom ==
                                  0) {
                                SystemChannels.textInput
                                    .invokeMethod('TextInput.show');
                              }
                              if (mounted) {
                                setState(() {
                                  _showKeyboard = !_showKeyboard;
                                });
                              }
                            },
                          ),
                          SizedBox(
                            width: 230,
                            child: TextField(
                              onTap: () {
                                if (mounted) {
                                  setState(() {
                                    _showKeyboard = true;
                                  });
                                }
                              },
                              controller: messageEditingController,
                              style: simpleTextStyle(),
                              textInputAction: TextInputAction.none,
                              decoration: InputDecoration(
                                hintText: "Escribe un mensaje",
                                hintStyle: TextStyle(
                                  color: Colors.black,
                                  fontSize: 16,
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    ClipOval(
                      child: Material(
                          color: Theme.of(context).primaryColorDark,
                          child: InkWell(
                            splashColor: Theme.of(context).accentColor,
                            child: IconButton(
                              color: Colors.white,
                              onPressed: () {
                                sendMessage();
                                //     addMessage();
                              },
                              icon: Icon(LineIcons.paper_plane),
                            ),
                          )),
                    ),
                  ],
                ),
              ),
            )
          ],
        ));
  }

}

2 个答案:

答案 0 :(得分:0)

您正在获取数据并调用setState((){}),它将更新UI。这也意味着您的StreamBuilder将被重建,而您正在使用 item = [];,这将在每次重建流构建器时清空列表。因此,您没有任何要显示的数据。

答案 1 :(得分:0)

感谢Shubham Gupta帮助我,这是对我有用的代码:

scipy.stats.ttest_ind