【问题标题】:A value of type 'StreamSubscription<DatabaseEvent>' can't be returned from the method 'getUsers' because it has a return type of 'Stream<List<User>>'无法从方法“getUsers”返回类型为“StreamSubscription<DatabaseEvent>”的值,因为它的返回类型为“Stream<List<User>>”
【发布时间】:2022-01-26 02:55:13
【问题描述】:

我正在使用我从github下载的教程构建一个聊天应用程序,但是由于它是由firestore制作的,并且人们建议用户firebase RTDB,所以现在我转换所有相关代码,我遇到的一个问题如下:

这是我的代码:

  static Stream<List<User>> getUsers() {
    return usersReference.onValue.listen((event){
            final data = Map<String, dynamic>.from(event.snapshot.value);
            final UserList = User.fromJson(data).toList();
            return UserList;
          });
  }

我想对以下小部件使用 getUsers() 方法:

Widget build(BuildContext context) =>
      Scaffold(
        backgroundColor: Colors.blue,
        body: SafeArea(
          child: StreamBuilder<List<User>>(
            stream: FirebaseApi.getUsers(),
            builder: (context, snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                default:
                  if (snapshot.hasError) {
                    print(snapshot.error);
                    return buildText('Something Went Wrong Try later');
                  } else {
                    final users = snapshot.data;

                    if (users.isEmpty) {
                      return buildText('No Users Found');
                    } else
                      return Column(
                        children: [
                          ChatHeaderWidget(users: users),
                          ChatBodyWidget(users: users)
                        ],
                      );
                  }
              }
            },
          ),
        ),
      );

这是为firestore制作的原始代码,我想用我的代码来替换:

   static Stream<List<User>> getUsers() => FirebaseFirestore.instance
       .collection('users')
       .orderBy(UserField.lastMessageTime, descending: true)
       .snapshots()
       .transform(Utils.transformer(User.fromJson));

所以这里出现了让我哭的错误:

A value of type 'StreamSubscription<DatabaseEvent>' can't be returned from the method 'getUsers' because it has a return type of 'Stream<List<User>>'.

如果您有任何线索如何使用 firebase rtdb,请帮助我,非常感谢,顺便说一句,为什么有这么多用于聊天应用程序的 firestore 教程会比 rtdb 更贵。

提前非常感谢,注意安全!

经过多次实验更新,我不确定以下是否是正确的解决方案:

  Stream<List<User>> getUsers() {
    getUserStream = usersReference.onValue.listen((event){
            final data = Map<String, dynamic>.from(event.snapshot.value);
            final userList = User.fromJson(data);
            return userList;
          });
  }

user.fromJson 的代码如下:

 static User fromJson(Map<String, dynamic> json) => User(
        idUser: json['idUser'],
        name: json['name'],
        urlAvatar: json['urlAvatar'],
        lastMessageTime: Utils.toDateTime(json['lastMessageTime']),
      );

所以这意味着我将数据从Json传输到List,我理解正确吗?感谢您的解释,这个社区非常友善,我只是一个软件初学者,但年龄超过 35 :)

绝望实验后更新,因为上面返回错误:

This function has a return type of 'Stream<List<User>>', but doesn't end with a return statement.

我尝试了另一种使用另一个小部件的解决方案:

  Widget build(BuildContext context) {
    return FirebaseAnimatedList(
        query: _usersReference.child("timestamp"),
        sort: (a, b) => (b.key.compareTo(a.key)),
        defaultChild: new CircularProgressIndicator(),
        itemBuilder: (context, snapshot, animation, index) {
          final data = Map<String, dynamic>.from(snapshot.value);
          final List<User> users = data.entries.map((e) => e.value).toList();
          return Column(
            children: [
              ChatHeaderWidget(users: users),
              ChatBodyWidget(users: users)
            ],
          );
        });
  }

所以根据我的理解,query: _usersReference.child("timestamp"),会给我一张地图,我只需要将列表转换为ChatHeaderWidget(users: users), 是否正确?

抱歉我的问题和日记很长,我现在无法测试,因为错误太多。

【问题讨论】:

    标签: flutter firebase-realtime-database


    【解决方案1】:
     Stream<List<User>> getUsers() {
        getUserStream = usersReference.onValue.listen((event){
                final data = Map<String, dynamic>.from(event.snapshot.value);
                final userList = User.fromJson(data);
                return userList;
              });
      }
    

    这个方法没有返回值。 usersReference.onValue 是一个流,你必须返回它。例如,您可以使用 Stream.map() 方法将流事件转换为您可以在 StreamBuilder 中使用的用户列表。

    所以一种可能的解决方案如下:

    Stream<List<User>> getUsers() => 
            FirebaseDatabase.instance.ref().onValue.map((event) =>
            event.snapshot.children
                .map((e) => User.fromJson(e.value as Map<String, dynamic>))
                .toList());
    

    我想象你的数据结构是这样的:

    "users": {
      "userId1": { /* userData */ },
      "userId2": { /* userData */ },
      "userId3": { /* userData */ }
    }
    

    现在您可以在 StreamBuilder 中接收实时数据库更改。你有一个用户列表,所以我认为你学习路径的下一步是在屏幕上显示这些用户。如果要使用 Column 进行测试,则必须生成它的所有子级。例如,您也可以在用户列表上使用 map 方法。

    Column(children: userList.map((user) => ListTile(title: Text(user.name))).toList())
    

    或其他解决方案

    Column(children: [
        for (var user in users) 
          ListTile(title: Text(user.name))
      ])
    

    【讨论】:

    • 在 getUsers 中,我得到参数类型“对象?”不能分配给参数类型“地图”。使用 .from(event.snapshot.value) 时。有什么建议吗?
    猜你喜欢
    • 2021-10-02
    • 2021-08-20
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 2021-01-25
    • 2022-01-15
    • 2021-09-14
    • 1970-01-01
    相关资源
    最近更新 更多