Флаттер StreamBuilder с нумерацией страниц Firestore - PullRequest
0 голосов
/ 13 февраля 2020

Я пытаюсь создать базовую функцию чата c, в которой все сообщения чата пользователей хранятся в виде документов в коллекции чатов. Я успешно реализовал разбиение на страницы, чтобы не перегружать данные, пока пользователь не выполнит прокрутку.

Однако, хотя у меня есть StreamBuilder, новые документы чата не появляются автоматически, как обычно. Почему Streambuilder не регистрирует и не отображает эти новые сообщения?

Вот мой код:

class MotivatorChat extends StatefulWidget {
  @override
  _MotivatorChatState createState() => _MotivatorChatState();
}

class _MotivatorChatState extends State<MotivatorChat> {

  Firestore firestore = Firestore.instance;
  List<DocumentSnapshot> chats = [];
  bool isLoading = false;
  bool hasMore = true;
  int documentLimit = 10;
  DocumentSnapshot lastDocument;
  ScrollController _scrollController = ScrollController();

  StreamController<List<DocumentSnapshot>> _controller = StreamController<List<DocumentSnapshot>>();

  Stream<List<DocumentSnapshot>> get _streamController => _controller.stream;


  @override
  void initState() {
    super.initState();
    getChats();
    _scrollController.addListener(() {
      double maxScroll = _scrollController.position.maxScrollExtent;
      double currentScroll = _scrollController.position.pixels;
      double delta = MediaQuery.of(context).size.height * 0.20;
      if (maxScroll - currentScroll <= delta) {
        getChats();
      }


    });
  }

  getChats() async {
    if (!hasMore) {
      print('No More Chats');
      return;
    }
    if (isLoading) {
      return;
    }
    setState(() {
      isLoading = true;
    });
    QuerySnapshot querySnapshot;
    if (lastDocument == null) {
      querySnapshot = await firestore
          .collection('chats')
          .orderBy('timestamp', descending: true)
          .limit(documentLimit)
          .getDocuments();
    } else {
      querySnapshot = await firestore
          .collection('chats')
          .orderBy('timestamp', descending: true)
          .startAfterDocument(lastDocument)
          .limit(documentLimit)
          .getDocuments();
      print(1);
    }
    if (querySnapshot.documents.length < documentLimit) {
      hasMore = false;
    }

    lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];

    chats.addAll(querySnapshot.documents);
    _controller.sink.add(chats);

    setState(() {
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {



    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Pagination with Firestore'),
      ),
      body: Column(children: [
        Expanded(
          child: StreamBuilder<List<DocumentSnapshot>>(
            stream: _streamController,
            builder: (sContext, snapshot) {
              print(snapshot.connectionState);
              if (snapshot.hasData && snapshot.data.length > 0) {
                return ListView.builder(
                  reverse: true,
                  controller: _scrollController,
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {
                    return Padding(
                      padding: EdgeInsets.only(top: 20),
                      child: Container(
                        height: 20,
                        child: Text(snapshot.data[index].data['text']),
                      ),
                    );
                  },
                );
              } else {
                return Center(
                  child: Text('No Data...'),
                );
              }
            },
          ),
        ),
        isLoading
            ? Container(
          width: MediaQuery
              .of(context)
              .size
              .width,
          padding: EdgeInsets.all(5),
          color: Colors.yellowAccent,
          child: Text(
            'Loading',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontWeight: FontWeight.bold,
            ),
          ),
        )
            : Container(),

      ]),
    );
  }
}

Обновлен StreamBuilder

StreamBuilder<List<DocumentSnapshot>>(
            stream: _streamController,
            builder: (sContext, snapshot) {
              if (snapshot.connectionState == ConnectionState.none) {
                return Text("None");
              } else if (snapshot.connectionState == ConnectionState.waiting) {
                return Text("Loading");
              } else if (snapshot.connectionState == ConnectionState.active) {
                if (snapshot.hasData && snapshot.data.length > 0) {
                  return ListView.builder(
                    reverse: true,
                    controller: _scrollController,
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: EdgeInsets.only(top: 20),
                        child: Container(
                          height: 20,
                          child: Text(snapshot.data[index].data['text']),
                        ),
                      );
                    },
                  );
                } else {
                  return Center(
                    child: Text('No Data...'),
                  );
                }
              } else {
                return Text("return list");
              }
            },
          ),

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Если hasMore равно false, поток не будет принимать новые данные.

не проверять hasMore

//     if (!hasMore) {
//       print('No More Chats');
//       return;
//     }

и проверять документы

//     if (querySnapshot.documents.length < documentLimit) {
//       hasMore = false;
//     }

    if (querySnapshot.documents.isEmpty) {
      print('No More Chats');
      setLoading(false);
      return;
    }

Я тестирую на DartPad , отправляет данные каждые 3 секунды.

0 голосов
/ 14 февраля 2020

Я пробую ваш код и установил лимит документа на 20, он работает нормально.

Пример на DartPad

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...