我正试图在Flutter中构建一个列表视图,以基于索引加载数据并按页记录
我能够显示固定数量的记录,但是需要一些帮助来获取和显示下一组记录,依此类推
这是我的代码段
Widget build(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
searchBoxWidget(),
Expanded(
child: FutureBuilder(
future: getRecordToDisplay(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
if (snapshot.hasError) {
return Text('You have some error : ');
} else if (snapshot.data != null) {
return buildListView(snapshot);
} else {
return Text('You have some error : ');
}
}
},
),
),
],
));
}
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {}
});
}
Future<Jobs> getRecordToDisplay() async {
return await getJobs(startPage, recordPerFetch);
}
ListView buildListView(AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.data.hits.length,
controller: _scrollController,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(
lobId: snapshot.data.hits[index].lobId,
atsReference: snapshot.data.hits[index].atsReference),
),
);
},
child: Container(
// width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(14.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Padding(
padding:
const EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Text(
snapshot.data.hits[index].title,
style: TextStyle(
color: Color(0xff2175D9),
fontSize: 18.0,
),
),
),
),
Icon(
Icons.arrow_forward,
color: Colors.blue,
)
],
),
Text(
snapshot.data.hits[index].jobLocation.city +
" , " +
snapshot
.data.hits[index].jobLocation.stateAbbreviation,
style: TextStyle(
color: Color(0xff0f1941),
fontSize: 16.0,
),
),
SizedBox(
height: 8.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
snapshot.data.hits[index].salary.salaryString,
style: TextStyle(
color: Color(0xff0f1941),
fontSize: 16.0,
),
),
Text(
snapshot.data.hits[index].createdDate,
style: TextStyle(
color: Color(0xff0f1941),
fontSize: 14.0,
),
),
],
),
SizedBox(
height: 8.0,
),
Divider(color: Colors.brown),
],
),
));
});
}
因此,它使用n条记录加载第一个记录,但是当您使用将来的构建器到达当前记录的底部时,我不知道如何加载下一组页面。
感谢您的帮助
答案 0 :(得分:0)
如果您希望显示无限列表,StreamBuilder 会不会更好?您是否有需要专门使用 FutureBuilder 的特定用例?这是一个简单的演示,它使用 Firestore 提供数据,并使用 ListView.builder
进行分页。
此示例实现了 Firebase 官方文档中 Firestore pagination 的片段。
在这个演示中有两种方法可以在视图上加载数据。
ListView
RefreshIndicator
ListView
中的下一个文档。
ScrollController
用于确定用户是否点击了列表的底部。import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'DocObj.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var scrollController = ScrollController();
@override
void initState() {
super.initState();
getDocuments();
scrollController.addListener(() {
if (scrollController.position.atEdge) {
if (scrollController.position.pixels == 0)
print('ListView scroll at top');
else {
print('ListView scroll at bottom');
getDocumentsNext(); // Load next documents
}
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: listDocument.length != 0
? RefreshIndicator(
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
controller: scrollController,
itemCount: listDocument.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('${listDocument[index].documentName}'),
);
},
),
onRefresh: getDocuments, // Refresh entire list
)
: CircularProgressIndicator(),
),
);
}
List<DocObj> listDocument;
QuerySnapshot collectionState;
// Fetch first 15 documents
Future<void> getDocuments() async {
listDocument = List();
var collection = FirebaseFirestore.instance
.collection('sample_pagination')
.orderBy("name")
.limit(15);
print('getDocuments');
fetchDocuments(collection);
}
// Fetch next 5 documents starting from the last document fetched earlier
Future<void> getDocumentsNext() async {
// Get the last visible document
var lastVisible = collectionState.docs[collectionState.docs.length-1];
print('listDocument legnth: ${collectionState.size} last: $lastVisible');
var collection = FirebaseFirestore.instance
.collection('sample_pagination')
.orderBy("name").startAfterDocument(lastVisible).limit(5);
fetchDocuments(collection);
}
fetchDocuments(Query collection){
collection.get().then((value) {
collectionState = value; // store collection state to set where to start next
value.docs.forEach((element) {
print('getDocuments ${element.data()}');
setState(() {
listDocument.add(DocObj(DocObj.setDocDetails(element.data())));
});
});
});
}
}
要解析文档中的数据,您可以为对象创建模型。
class DocObj {
var documentName;
DocObj(DocObj doc) {
this.documentName = doc.getDocName();
}
dynamic getDocName() => documentName;
DocObj.setDocDetails(Map<dynamic, dynamic> doc)
: documentName = doc['name'];
}
该示例处理来自 Firestore 的数据。
这是应用运行时的外观。