I'm building a selectable checkbox contact list in flutter but if a contact has only an email and no number, an error is thrown. I want to create a loop to add a number of '99999' to the contacts phone number if they don't have one. Please can someone guide me with an explanation of what I should change to make this work? I have had a go, but I am quite new to flutter so I'm not completely certain on syntax etc...

Here is the part of the code that I am trying to put the function into.

setMissingNo()async {
  Iterable<Contact> contactsToLoop = (await ContactsService.getContacts()).toList();
  contactsToLoop.forEach((Contact) { contactsToLoop = []..add(Item.fromMap({'label': 'work', 'value': 99999})); });
}

//fetch contacts from setMissingNo
  getAllContacts() async{
  Iterable<Contact> _contacts = (await ContactsService.getContacts()).toList(); 

setState(() {
  contacts = _contacts;
  }
  );
}

Here is my whole code

import 'package:flutter/material.dart';
// TODO: make it ask for permissions otherwise the app crashes
import 'package:contacts_service/contacts_service.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
List<Contact> contacts = [];
List<Contact> contactsFiltered = [];
TextEditingController searchController = new TextEditingController();

@override
  void initState() {
    super.initState();
    getAllContacts();
    searchController.addListener(() => filterContacts());
  }

//remove the +'s and spaces from a phone number before its searched
 String flattenPhoneNumber(String phoneStr) {
    return phoneStr.replaceAllMapped(RegExp(r'^(\+)|\D'), (Match m) {
      return m[0] == "+" ? "+" : "";
    });
  }

//loop and set all contacts without numbers to 99999, pass new list to getAllContacts
setMissingNo()async {
  Iterable<Contact> contactsToLoop = (await ContactsService.getContacts()).toList();
  contactsToLoop.forEach((Contact) { contactsToLoop = []..add(Item.fromMap({'label': 'work', 'value': 99999})); });
}

//fetch contacts from setMissingNo
  getAllContacts() async{
  Iterable<Contact> _contacts = (await ContactsService.getContacts()).toList(); 

setState(() {
  contacts = _contacts;
  }
  );
}

//filtering contacts function to match search term
 filterContacts() {
    List<Contact> _contacts = [];
    _contacts.addAll(contacts);
    if (searchController.text.isNotEmpty) {
      _contacts.retainWhere((contact) {
        String searchTerm = searchController.text.toLowerCase();
        String searchTermFlatten = flattenPhoneNumber(searchTerm);
        String contactName = contact.displayName.toLowerCase();
        bool nameMatches = contactName.contains(searchTerm);
        if (nameMatches == true) {
          return true;
        }

        if (searchTermFlatten.isEmpty) {
          return false;
        }

        var phone = contact.phones.firstWhere((phn) {
          String phnFlattened = flattenPhoneNumber(phn.value);
          return phnFlattened.contains(searchTermFlatten);
        }, orElse: () => null);

        return phone != null;
      });

      setState(() {
        contactsFiltered = _contacts;
      });
    }
  }

final selectedContacts = Set<Contact>();

  @override
  Widget build(BuildContext context) {
    bool isSearching = searchController.text.isNotEmpty;

    return Scaffold(
      body: SafeArea(
        child: Column(
          children: <Widget>[

            AppBar(
              title: Text('Create Group'),
            ),

            Container(
              child: TextField(
                controller: searchController,
                decoration: InputDecoration(
                  labelText: 'Search Contacts',
                  border: OutlineInputBorder(
                    borderSide: new BorderSide(
                      color: Theme.of(context).primaryColor
                    )
                  ),
                  prefixIcon: Icon(
                    Icons.search,
                    color: Theme.of(context).primaryColor
                  )
                ),
              ),
            ),

                 Expanded( child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: isSearching == true ? contactsFiltered.length : contacts.length,
                    itemBuilder: (context, index) {
                    Contact contact = isSearching == true ? contactsFiltered[index] : contacts[index];
                    //TODO: make it so when you clear your search, all items appear again & when you search words it works
                    return CheckboxListTile(
                      title: Text(contact.displayName),
                      subtitle: Text(
                        contact.phones.elementAt(0).value
                        ),                      
                       value: selectedContacts.contains(contact),
                  onChanged: (bool value) { 
                    if (value) { 
                      selectedContacts.add(contact); 
                    } else {
                      selectedContacts.remove(contact); 
                    }
                    setState((){}); 

                               // TODO: add in function to add contact ID to a list
                           });
                          },
                          ),

                    /*new Expanded(
                    child: Align(
                    alignment: Alignment.bottomLeft,
                     child: BottomNavigationBar(  
                currentIndex: _currentIndex,   

        items: const <BottomNavigationBarItem>[

//TODO: create new contact functionality to add someone by name + email
          BottomNavigationBarItem(
            icon: Icon(Icons.add),
            title: Text('Add Contact'),
          ),

          BottomNavigationBarItem(
            icon: Icon(Icons.create),
            title: Text('Create Group'),
          ),

        ],  
        onTap: (index) {
                  setState(() {
                  _currentIndex = index;
                  });     
                  }
        )
                    )
        )*/
        )
          ],
        )
      ),
    );
  }
}


Solution 1: Omatt

Updating all contacts listed on the device might take a long time depending on the size of the device's contact list. Add that the task is being done on the UI thread. You may want to consider using Isolate for the task to move away the load from the UI thread. If you can also provide the errors that you're getting, it'll help us get a picture of the issue.

Another thing is, the way you're approaching the issue might be impractical. Is it really necessary to write a placeholder phone number to the contacts? The issue likely stems from trying to fetch the number from a contact but the Object returns null. Perhaps you may want to consider only updating the phone number when the contact is selected.