StreamBuilder在滚动端调用两次

时间:2019-09-05 16:56:58

标签: flutter

我正在将ListView@override void initState() { _scrollController = ScrollController(); _scrollController.addListener( () { if ( _scrollController.offset >= _scrollController.position.maxScrollExtent && !_scrollController.position.outOfRange ) { setState( () {} ); } }); super.initState(); } Stream<QuerySnapshot> _getFirestoreStream(int subj, int type, DocumentSnapshot lastRead){ return lastRead == null ? Firestore.instance .collection(types[subj][type]) .limit(25) .orderBy("votes", descending: true) .snapshots() : Firestore.instance .collection(types[subj][type]) .limit(25) .orderBy("votes", descending: true) .startAfterDocument(lastRead) .snapshots(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("My App"), centerTitle: true, ), body: Padding( padding: const EdgeInsets.all(16.0), child: StreamBuilder<QuerySnapshot>( stream: _getFirestoreStream(_subject, _docType, _lastDocumentRead), builder: (context, snapshots) { if(!snapshots.hasData){ return Center( child: CircularProgressIndicator( strokeWidth: 8.0, ), ); } else { _updateItems(snapshots.data.documents); return Column( children: <Widget>[ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ DropdownButton( value: _subject, onChanged: (val) => setState(() { _subject = val; _docType = 0; _lastDocumentRead = null; }), items: subjects.asMap().entries.map((map) => DropdownMenuItem( value: map.key, child: Text(map.value), ), ).toList(), ), DropdownButton( value: _docType, onChanged: (val) => setState(() { _docType = val; _lastDocumentRead = null; }), items: types[_subject].asMap().entries.map((map) => DropdownMenuItem( value: map.key, child: Text(map.value), ), ).toList(), ), ], ), Expanded( child: ListView.builder( controller: _scrollController, padding: const EdgeInsets.only(top: 12.0), itemCount: items.length, itemBuilder: (context, i) => _buildListItem( context, items.elementAt(i), ), // itemBuilder, ), ), ], ); } }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { showDialog( context: context, builder: (context) { return AddNameDialog(); } ); }, tooltip: 'Add Name', child: Icon(Icons.add, size: 40), ), ); } void _updateItems(List<DocumentSnapshot> docs) { items.addAll(docs); _lastDocumentRead = items.last; } 一起使用。到达列表末尾时,它应从上次读取的文档(Firestore的分页)开始加载更多项目。

由于某种原因,每次到达流的末尾时,流的构建器函数都会被调用两次,而我不明白其原因。

// Example:
0: Stream[0]

// onNextCall
0: Stream[0]
1: Stream[1]
2: Stream[0]

// onNextCall
0: Stream[0]
1: Stream[1]
2: Stream[0]
3: Stream[2]
4: Stream[1]

// ...

我希望每个“刷新”(setState())流都会被调用一次,但是_getFirestoreStream每次到达底部时都会被调用两次,发现的结果类似于“新结果+旧结果”。

zeros(number){
  if(number == 0 ) //return 1
  if(number < 10) //return 0
  else
       zeros(number/10) + zeros(number%10)
}

我的列表结果正在发生类似上述的事情。

有人可以帮我理解是什么导致两次调用流吗?

我在上面发布了我的构建代码和相关功能。

0 个答案:

没有答案