如何将 Firestore 文档从流传递到 Flutter 中的下一页?
How to pass a Firestore document from a stream to next page in Flutter?
我有一个列表视图,其中每个项目都是来自 firestore 集合的一个文档。我想点击项目并将文档信息传递到详细信息页面。
这是我在第一个流中检索文档信息的方式:
child: Text(streamSnapshot.data.docs[index]['event_title'],
这就是我尝试将数据发送到下一页的方式:
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, EventPage.id, arguments: streamSnapshot.data.docs[index]);
},
我不知道如何接收传递的数据:
class _EventPageState extends State<EventPage> {
@override
final db = FirebaseFirestore.instance;
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments;
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('event_title'),
),
child: Column(
我知道我需要下一页的 StreamBuilder,但是您是否知道如何使该流仅显示传入的文档?
为什么不改用 Provider?它将帮助您避免样板代码,并且当您使用流时,它将让您以更好的方式处理信息。检查一下 here
我已经找到了这个问题的答案。我敢肯定有几种方法可以做到这一点,但这是我的方法:
关键是将 firestore 文档 ID 传递到下一页。在此示例代码中,我将 streamSnapshot.data.docs[index].id.toString()
作为参数传递给自定义小部件。我在那个小部件中找到了我命名的路线。
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('events')
.where('start_date', isGreaterThanOrEqualTo: DateTime.now())
.snapshots(),
builder: (context, AsyncSnapshot streamSnapshot) {
if (!streamSnapshot.hasData) {
return SizedBox(
height: 250,
child: Center(
child: CircularProgressIndicator(),
),
);
} else
return SizedBox(
height: 250,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: streamSnapshot.data.docs.length,
itemBuilder: (ctx, index) =>
EventListHorizontalTile(
//passes the document ID as a string down to the horizontally scrollable tile,
//where we push a named route with the docID string as an argument
firestoreDocID: streamSnapshot.data.docs[index].id.toString(),
image: streamSnapshot.data.docs[index]['main_image'],
name: streamSnapshot.data.docs[index]['name'],
),
),
);
}),
然后我创建了一个 class 作为参数通过命名路由传递。
class Events {
final String firestoreDocID;
Events({
required this.firestoreDocID,
});
}
现在,在我的 EventListHorizontalTile
小部件中:
class EventListHorizontalTile extends StatelessWidget {
const EventListHorizontalTile({
Key? key,
required this.name,
this.firestoreDocID = '',
}) : super(key: key);
final String name;
final String firestoreDocID;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
//Here I am pushing a named route with an argument, using that Events class I made earlier.
Navigator.pushNamed(context, EventPage.id, arguments: Events(firestoreDocID: firestoreDocID));
},
//child: The rest of the list tile widget
),
现在我们必须在 EventPage
中编写一些代码来接收参数。
class EventPage extends StatefulWidget {
const EventPage({
Key? key,
}) : super(key: key);
static String id = 'EventPage';
@override
_EventPageState createState() => _EventPageState();
}
class _EventPageState extends State<EventPage> {
@override
Widget build(BuildContext context) {
//This is how we receive the argument.
final args = ModalRoute.of(context)!.settings.arguments as Events;
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
//Some text to see if the string made it.
Text(args.firestoreDocID),
]),
),
);
}
}
就是这样!在新页面中获得该文档 ID 后,您可以这样调用 Streambuilder
:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('events')
.doc(args.firestoreDocID)
.snapshots(),
我有一个列表视图,其中每个项目都是来自 firestore 集合的一个文档。我想点击项目并将文档信息传递到详细信息页面。
这是我在第一个流中检索文档信息的方式:
child: Text(streamSnapshot.data.docs[index]['event_title'],
这就是我尝试将数据发送到下一页的方式:
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, EventPage.id, arguments: streamSnapshot.data.docs[index]);
},
我不知道如何接收传递的数据:
class _EventPageState extends State<EventPage> {
@override
final db = FirebaseFirestore.instance;
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments;
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('event_title'),
),
child: Column(
我知道我需要下一页的 StreamBuilder,但是您是否知道如何使该流仅显示传入的文档?
为什么不改用 Provider?它将帮助您避免样板代码,并且当您使用流时,它将让您以更好的方式处理信息。检查一下 here
我已经找到了这个问题的答案。我敢肯定有几种方法可以做到这一点,但这是我的方法:
关键是将 firestore 文档 ID 传递到下一页。在此示例代码中,我将 streamSnapshot.data.docs[index].id.toString()
作为参数传递给自定义小部件。我在那个小部件中找到了我命名的路线。
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('events')
.where('start_date', isGreaterThanOrEqualTo: DateTime.now())
.snapshots(),
builder: (context, AsyncSnapshot streamSnapshot) {
if (!streamSnapshot.hasData) {
return SizedBox(
height: 250,
child: Center(
child: CircularProgressIndicator(),
),
);
} else
return SizedBox(
height: 250,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: streamSnapshot.data.docs.length,
itemBuilder: (ctx, index) =>
EventListHorizontalTile(
//passes the document ID as a string down to the horizontally scrollable tile,
//where we push a named route with the docID string as an argument
firestoreDocID: streamSnapshot.data.docs[index].id.toString(),
image: streamSnapshot.data.docs[index]['main_image'],
name: streamSnapshot.data.docs[index]['name'],
),
),
);
}),
然后我创建了一个 class 作为参数通过命名路由传递。
class Events {
final String firestoreDocID;
Events({
required this.firestoreDocID,
});
}
现在,在我的 EventListHorizontalTile
小部件中:
class EventListHorizontalTile extends StatelessWidget {
const EventListHorizontalTile({
Key? key,
required this.name,
this.firestoreDocID = '',
}) : super(key: key);
final String name;
final String firestoreDocID;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
//Here I am pushing a named route with an argument, using that Events class I made earlier.
Navigator.pushNamed(context, EventPage.id, arguments: Events(firestoreDocID: firestoreDocID));
},
//child: The rest of the list tile widget
),
现在我们必须在 EventPage
中编写一些代码来接收参数。
class EventPage extends StatefulWidget {
const EventPage({
Key? key,
}) : super(key: key);
static String id = 'EventPage';
@override
_EventPageState createState() => _EventPageState();
}
class _EventPageState extends State<EventPage> {
@override
Widget build(BuildContext context) {
//This is how we receive the argument.
final args = ModalRoute.of(context)!.settings.arguments as Events;
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
//Some text to see if the string made it.
Text(args.firestoreDocID),
]),
),
);
}
}
就是这样!在新页面中获得该文档 ID 后,您可以这样调用 Streambuilder
:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('events')
.doc(args.firestoreDocID)
.snapshots(),