I am using this package to retrieve device's contacts. The lib retrieve 427 contacts and I want to loop the whole list so that I can create another list and send it to the back-end. The problem is looping does not work this the function return before looping is completed.

Here the function I use:

  Future<QueryResult> uploadContacts() async {
    final List<Contact> rawContacts =
        (await ContactsService.getContacts(withThumbnails: false)).toList();
    List<ContactInput> contactsListInput;

    print('contactsListInput length: ${rawContacts.length}');

    rawContacts.forEach((contact) {
      print('contact: $contact'); //PRINTED JUST ONCE

      //Contact can have more than 1 number. We need them all
      contact.phones.forEach((phone) {
        final contactInput =
            ContactInput(name: contact.displayName, phone: phone.value);

        contactsListInput.add(contactInput);
      });
    });

    print('contactsListInput length: ${contactsListInput.length}'); //NEVER PRINT ANYTHING

    final ContactsListInput input =
        ContactsListInput(contacts: contactsListInput);

    final MutationOptions _options = MutationOptions(
        document: SyncContactsMutation().document,
        variables: SyncContactsArguments(input: input).toJson());

    return client.mutate(_options);
  }

I have also tried using for loop and the same thing happened.

    for (int i = 0; i < rawContacts.length; i++) {
      final contact = rawContacts[i];

      final contactInput =
      ContactInput(name: contact.displayName, phone: contact.phones.first.value);

      contactsListInput.add(contactInput);
    }
    print('contactsListInput length: ${contactsListInput.length}'); //NEVER CALLED

And I also tried Future.forEach

    await Future.forEach(rawContacts, (contact) async {
      print('contact: $contact');

      //Since contact can have more than one number we loop them too.
      await Future.forEach(contact.phones, (phone) async {
        final contactInput =
            ContactInput(name: contact.displayName, phone: phone.value);

        contactsListInput.add(contactInput);
      });
    });

How to fix this? Any help will be much appreciated.


Solution 1: Nux

I have fixed it as

  Future<QueryResult> uploadContacts() async {
    final Iterable<Contact> rawContacts =
        (await ContactsService.getContacts(withThumbnails: false));

    final Iterable<ContactInput> contacts = rawContacts.expand((contact) => contact.phones.map(
        (phone) =>
            ContactInput(name: contact.displayName, phone: phone.value)));

    final input = ContactsListInput(contacts: contacts);

    final MutationOptions _options = MutationOptions(
        document: SyncContactsMutation().document,
        variables: SyncContactsArguments(input: input).toJson());

    return client.mutate(_options);
  }

Credit goes to @pskink and @loganrussell48


Solution 2: Danhausen

You should use it as a dynamic type object. Try something like this:

(event.snapshot.value as dynamic).forEach()

Try and see if it works.