Home > other >  A value of type 'StreamSubscription<DatabaseEvent>' can't be returned from the
A value of type 'StreamSubscription<DatabaseEvent>' can't be returned from the

Time:12-28

I am building a chat app with the tutorial I downloaded from github, but since it is made by firestore, and people suggests to user firebase RTDB, so now Im transforming all the related code, one problem I met is followings:

This is my code:

  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;
          });
  }

I wan to use methode getUsers() for this following widget:

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

This is original code made for firestore, which I want to use my code to replace:

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

So here comes error which makes me crying:

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

Plz, plz help me if you have any clue how to use firebase rtdb, thanks a lot, and btw why there is so many firestore tutorial for chat app which will be more expensive instead of rtdb.

Thanks a lot in advance and keep safe!

Updated after several experiment, Im not sure if following is correct solution:

  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;
          });
  }

for user.fromJson is followings code:

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

So it means I transfer the data from Json to List, do I understand it correctly? Thanks for explaining, it is very kind of this community, Im just a software beginner but older than 35:)

updated after despairing experiment since above return an error:

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

I tried another solution which use another widget:

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

so from my poor understanding query: _usersReference.child("timestamp"),will give me a map and I just need to convert to a List to ChatHeaderWidget(users: users), is it correct?

Sorry for my long question and diary, I can not test it now, since there are too many error yet.

CodePudding user response:

 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;
          });
  }

There is no return value in this method. usersReference.onValue is a stream, you have to return with that. And for example you can use Stream.map() method to convert stream events to user list you can use in the StreamBuilder.

So one possible solution is the following:

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

I imagined your data structure is something like this:

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

Now you receive realtime database changes in your StreamBuilder. You have a list of users so I think your next step in your learning path to show these users on the screen. If you want to test with Column, you have to generate all children of it. For example you can use the map method on the user list too.

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

or another solution

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