firebase - 如何在列表视图的滚动中添加更多项目?
问题描述
此处的代码当前加载了存储在 Firestore 集合中的所有 brews。我如何最初仅加载 10 个 brews,然后当用户向下滚动并到达 10 个 brews 列表的末尾时。它应该加载最后一次冲泡后还有 10 个......并且冲泡应根据时间戳进行排序。
class BrewList extends StatefulWidget {
@override
_BrewListState createState() => _BrewListState();
}
class _BrewListState extends State<BrewList> {
List<Brew> brews = [];
ScrollController _controller = ScrollController();
@override
void initState() {
_startFirst();
super.initState();
_controller.addListener(_scrollListener);
}
_scrollListener() {
setState(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0) {
} else {
}
}
});
}
_startFirst() async {
brews = await DatabaseService().brews ?? [];
setState(() {
brews = brews;
});
}
@override
Widget build(BuildContext context) {
Future<void> _refreshBrews() async {
List<Brew> tempList = await DatabaseService().brews;
setState(() {
brews = tempList;
});
print(brews);
}
return RefreshIndicator(
onRefresh: _refreshBrews,
child: ListView.builder(
controller: _controller,
itemCount: brews.length,
itemBuilder: (context, index) {
return BrewTile(brew: brews[index]);
},
),
);
}
}
Future<List<Brew>> get brewss async {
QuerySnapshot snapshot = await brewsCollection
.orderBy('timestamp', descending: true)
.limit(2)
.getDocuments();
return _postListFromSnapshot(snapshot);
}
解决方案
不确定以下是否会有所帮助,但这是我在颤振应用程序中所做的。特别注意底部的 _onScroll 函数。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../blocs/feed_bloc/feed_events.dart';
import '../../blocs/feed_bloc/bloc.dart';
import '../../blocs/feed_bloc/feed_state.dart';
import './post.dart';
import '../loader.dart';
class Feed extends StatefulWidget {
Feed({ Key key }): super(key: key);
@override
_FeedState createState() => _FeedState();
}
class _FeedState extends State<Feed> {
final _scrollController = ScrollController();
final _scrollThreshold = 300.0;
FeedBloc _feedBloc;
_FeedState();
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
_feedBloc = BlocProvider.of<FeedBloc>(context);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<FeedBloc, FeedState>(
builder: (context, state) {
if (state is FeedUninitialized) {
_feedBloc.add(Init());
return Loader();
}
if (state is FeedLoading) {
return Loader();
}
if (state is FeedLoaded) {
return new RefreshIndicator(
child: ListView(
controller: _scrollController,
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: state.posts.map((post) {
return Post(
postModel: state.postMap[post]
);
}).toList(),
),
onRefresh: () {
_feedBloc.add(Refresh());
return new Future.delayed(new Duration(seconds: 1));
},
);
}
return Center(
child: SizedBox(
height: 33,
child: Text(
'Sorry, there was a problem loading the feed.',
style: TextStyle( color: Colors.white)
),
),
);
}
);
}
int lastScroll = 0;
void _onScroll() {
if (new DateTime.now().millisecondsSinceEpoch - lastScroll > 1000) {
lastScroll = new DateTime.now().millisecondsSinceEpoch;
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll <= _scrollThreshold) {
_feedBloc.add(Fetch());
}
}
}
}
我认为您需要的是 startAfterDocument。见下文...
Future<Map<String, dynamic>> getPosts({PostModel parent, PostModel lastPost}) async {
// First, we create the initial query.
// We pass in the parent key if there is one.
Query query = Firestore.instance
.collection('posts');
if (parent != null) {
query = query.where('parentId', isEqualTo: parent.key);
} else {
query = query.where('parentId', isNull: true);
}
query = query.orderBy('timestamp', descending: true);
// If we want to start at a certain doc (user is scrolling throught he feed)
// then we specify to start after a certain doc
if (lastPost != null) {
query = query.startAfterDocument(lastPost.rawDoc);
}
// Execute the query
final results = await query
.limit(18)
.getDocuments();
// Create some Lists/Maps we're going to need
List<String> posts = new List<String>();
Map<String, PostModel> postMap = new Map<String, PostModel>();
Map<String, bool> likeMap = new Map<String, bool>();
// Convienience/Brevity
final List<DocumentSnapshot> documents = results.documents;
final int numDocs = documents.length;
if (numDocs > 0) {
final firstDoc = results.documents[0].data;
final lastDoc = results.documents[numDocs-1].data;
// Get all your likes for a certain date range that aligns with the
// documents we just retrieved
likeMap = await getLikes(firstDoc['postCreated'], lastDoc['postCreated']);
}
// Loop through, and create all the PostModels
for (int i = 0; i < numDocs; i++) {
DocumentSnapshot doc = documents[i];
PostModel post = snapshotToPostModel(doc, likeMap[doc.documentID]);
postMap[doc.documentID] = post;
posts.add(post.key);
}
final Map<String, dynamic> res = new Map<String, dynamic>();
res['posts'] = posts;
res['postMap'] = postMap;
return res;
}