简体   繁体   English

如何将 stream 中的 Firestore 文档传递到 Flutter 中的下一页?

[英]How to pass a Firestore document from a stream to next page in Flutter?

I have a listview where each item is one document from a firestore collection.我有一个列表视图,其中每个项目都是来自 firestore 集合的一个文档。 I would like to tap the item and pass the document information to a details page.我想点击该项目并将文档信息传递到详细信息页面。

This is how I am retrieving document information within the first stream:这是我在第一个 stream 中检索文档信息的方式:

child: Text(streamSnapshot.data.docs[index]['event_title'],

This is how I'm attempting to send the data to the next page:这就是我试图将数据发送到下一页的方式:

child: GestureDetector(
                          onTap: () {
                            Navigator.pushNamed(context, EventPage.id, arguments: streamSnapshot.data.docs[index]);
                          },

I'm lost as to how to receive the passed data:我不知道如何接收传递的数据:

    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(

I know I need a StreamBuilder on the next page, but do you have any insight on how to make that stream show only the passed in document?我知道下一页需要一个 StreamBuilder,但是您是否知道如何使 stream 仅显示传入的文档?

Why don't you use Provider instead?为什么不改用 Provider 呢? It'll help you to avoid boiler plate and as you're using streams it'll let you handle information in a better way.它将帮助您避免样板代码,并且当您使用流时,它会让您以更好的方式处理信息。 Check about it here在这里查看

I have worked out an answer to this question.我已经找到了这个问题的答案。 I'm sure there are several ways to do this, but here's mine:我敢肯定有几种方法可以做到这一点,但这是我的:

The key is to pass the firestore document ID to the next page.关键是将 firestore 文档 ID 传递给下一页。 In this example code, I pass streamSnapshot.data.docs[index].id.toString() as a parameter to a custom widget.在此示例代码中,我将streamSnapshot.data.docs[index].id.toString()作为参数传递给自定义小部件。 I've located my named route within that widget.我在那个小部件中找到了我命名的路线。

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'],
              ),
          ),
        );
    }),

I then created a class to pass as an argument through a named route.然后我创建了一个 class 作为参数通过命名路由传递。

class Events {
  final String firestoreDocID;

  Events({
    required this.firestoreDocID,

  });

}

Now, within my EventListHorizontalTile widget:现在,在我的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

),

Now we have to write a bit of code in the EventPage to receive the argument.现在我们必须在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),

]),
),
);
}
}

And that's it, Once you have that document ID in your new page, you can call a Streambuilder like this:就是这样,一旦您在新页面中有了该文档 ID,您就可以像这样调用Streambuilder

StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection('events')
                  .doc(args.firestoreDocID)
                  .snapshots(),

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM