我正在将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)
}
我的列表结果正在发生类似上述的事情。
有人可以帮我理解是什么导致两次调用流吗?
我在上面发布了我的构建代码和相关功能。