1

I have a StreamProvider here:

final secondTabProvider = StreamProvider((ref){
  EmergencyContactsController contacts = EmergencyContactsController(currentUserID: ref.read(authProvider).currentUser!.uid);
  return contacts.getUserEmergencyContacts();
});

And I call it in my build method like so:

_secondTab.when(
  data: (data) {
    if (!data.exists){
     return Text("no data")
    }

    Map<String, dynamic doc = data.doc() as Map<String, dynamic>;
    
    List conversations = doc['conversation'];

    // Store the user profiles
    List<EmergencyContactModel> users = [];

    for (Map<String, dynamic> user in userConversations){
                              
      contacts.getContactInfo(
       uid: user['userID']
      ).then((value){
        if (value != null){
         EmergencyContactModel contact = EmergencyContactModel.fromJson(value);

         contact.messageID = value["id"] + ref.read(authProvider).currentUser!.uid;
         users.add(contact);
        }

      });
    }

   return Listview.builder(
    itemCount: users.length,
    itemBuilder: (BuildContext context, int index) => Text(users[index]['name'])
   );
  },
  error: (err, _){
   return Text("Error")
  },
  loading: () => CircularProgressIndicator()

)

The contacts.getContactInfo() method is an async and I need it to execute before the loop continues to the next iteration, but it's not doing that. Any help would be largely appreciated.

Dre Day
  • 25
  • 8

1 Answers1

0

I solved it. I converted the for loop into its own async function as seen below:

// Generate a list of users that the current user has had conversations with
  userinfoGenerator(List userIDs) async {
    // Get the user profiles
    List<EmergencyContactModel> users = [];

    for (Map<String, dynamic> user in userIDs){
     
      Map<String, dynamic>? contactInfo = await contacts.getContactInfo(uid: user['userID']);

      if (contactInfo != null){
        EmergencyContactModel contact = EmergencyContactModel.fromJson(contactInfo);
        contact.messageID =  contactInfo["id"] + ref.read(authProvider).currentUser!.uid;
        users.add(contact);
      }

    }

    return users;
  }

And then I used a Future Builder to return the result of the function as seen below:

return FutureBuilder(
    future: userinfoGenerator(userConversations),
    builder: (BuildContext context, AsyncSnapshot snapshot){

      // Checking if future is resolved
      if (snapshot.connectionState == ConnectionState.done) {
        // If we got an error
        if (snapshot.hasError) {
          return Center(
            child: CustomText(
              label: '${snapshot.error} occurred',
            ),
          );

          // if we got our data
        } else if (snapshot.hasData) {
          // Extracting data from snapshot object
          final data = snapshot.data;
          return ListView.builder(
              shrinkWrap: true,
              itemCount: data.length,
              itemBuilder: (BuildContext context, int index) {
                List<String> theName = data[index].name
                    .split(" ");
                return Padding(
                  padding: const EdgeInsets.only(
                      top: 12.0),
                  child: CustomListTile(
                      contact: data[index],
                      label: theName.length == 1
                          ? theName[0][0]
                          : "${theName[0][0]} ${theName[theName
                          .length - 1][0]}"
                  ),
                );
              }
          );
        }
      }

      return const Center(
        child: CircularProgressIndicator(
          color: kDefaultBackground,
        ),
      );
    },
  );
Dre Day
  • 25
  • 8