【问题标题】:How to use firebase collection length in list view builder flutter null safety如何在列表视图构建器中使用firebase集合长度flutter null安全
【发布时间】:2021-09-20 01:40:18
【问题描述】:

我对 Flutter 和 firebase 比较陌生,并试图从一组消息中检索消息,每个消息都具有消息文本、发件人等消息属性。 但是,当使用列表视图构建器时,我不能使用 itemcount,因为它说,Future 不能用来代替 int 或“不能无条件调用数据,因为它可能为空”。添加空检查(!)会导致它说它不能用于对象。请帮忙。

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MaterialApp(
      home: readMessage(),
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.purple,
      )));
}

class readMessage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _readMessageState();
  }
}

class _readMessageState extends State<readMessage> {
  bool isMe = true;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: FirebaseFirestore.instance
            .collection('users')
            .doc('ItpNRR6uNfl4Mf4qvlIa')
            .collection('messages')
            .snapshots(),
        builder: ((context, snapshot) {
          /// This is where I need the listview builder of collection inside the document
        }));
  }

  BoxDecoration messageBubbleMaker(bool isMe){
    return BoxDecoration(
      borderRadius: BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20), bottomRight: isMe? Radius.zero : Radius.circular(20), bottomLeft: !isMe? Radius.zero : Radius.circular(20)),
      color: isMe? Colors.black : Colors.blueAccent
    );
  }
}


这是我的代码。

it supports null safety

【问题讨论】:

    标签: firebase flutter dart


    【解决方案1】:

    对于您的流,您需要将每个快照从 json 转换为对象,然后将其转换为列表。然后,您可以在您的ListView.builder 中使用snapshot.data.length 作为itemcount。例如,

     return StreamBuilder(
                stream: FirebaseFirestore.instance
                    .collection('users')
                    .doc('ItpNRR6uNfl4Mf4qvlIa')
                    .collection('messages')
                    .snapshots().map((snapshot) =>
                        snapshot.docs.map((doc) => Message.fromJson(doc.data())).toList()),
                builder: ((context, snapshot) {
                  ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (context, index) {
                      // return something for every item in the list
                    }),
                }));
    

    还有一个名为 message.dart 的消息模型类。例如:

    class Message {
      final String messageId;
      final String content;
    
      Message(this.messageId, this.content);
    
      Message.fromJson(Map<String, dynamic> json)
          : messageId = json['messageId'],
            content = json['content'];
    
      Map<String, dynamic> toJson() => {
            'messageId': messageId,
            'content': content,
          };
    }
    

    【讨论】:

    • map((snapshot) => snapshot.docs.map((doc) => Messages.fromJson(doc.data())).toList()) 它有什么作用?
    • Messages.fromJson。什么是消息?
    • 你必须有一个模型类 Message.dart ,其中包含 'messages' 集合的所有文档字段。这个类还将有两个函数,一个用于从 Json(即从 firestore)获取数据,另一个用于将其映射并存储到 firestore。因此,Message.fromJson 是一个将文档从 json 转换为 Flutter 读取的函数。虽然您必须为消息执行此操作,但可以在此处找到为用户执行此操作的示例:flutter.dev/docs/development/data-and-backend/json
    • 我为答案中的消息添加了一个示例模型类
    • 我是新手,没有得到模型。我仍然在学习。你能解释一下 Messages.fromJson 来自哪里,因为它没有定义
    【解决方案2】:

    这行得通

    StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection('collection name')
                  .doc('doc id')
                  .collection('collection name')
                  .snapshots();
    
    

    获取一个集合作为 QuerySnapshot(数据类型)。 如果您使用的是文档,那么它将是 DocumentSnapshot 而不是 querySnapshot

    现在在构建器中

    builder: ((context, snapshot) {
        if (snapshot.hasData) {
          var collectionData = snapshot.data as QuerySnapshot;
        }
    

    这将检查数据的存在和可选但推荐。

    您可以在没有 if 语句的情况下定义 collectionData 或使用 ?像插值一样

    snapshot.hasData ? <What to do if true> : <what to do if false>
    

    在上面相同的 if 语句中的 listview builder 中:

    itemCount: messages.docs.length,
    itembuilder: (BuildContext context, int index)
                              {
                                var collectionDataList = collectionData.docs.toList();
                                var CollectionDoc = collectionDataList[index];
                                return Text(CollectionDoc['field name']);
                              })
    

    用您喜欢的任何内容替换文本字段,例如聊天应用程序的自定义消息气泡生成器,您可以在其中提供字段值作为参数。

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 1970-01-01
      • 2021-10-19
      • 2019-05-27
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2020-11-10
      相关资源
      最近更新 更多