Flutter - Pass a Future List to a SearchDelegate

5,632

Basically you have to move the FutureBuilder further up the widget hierarchy, so both the search box as well as the body are below it. Then you can simply push your data into the ContactSearch.

For Example:

@override
Widget build(BuildContext context) {
  return FutureBuilder<List<Contact>>(
      future: readContacts(),
      builder: (context, snapshot) {
        return Scaffold(
          appBar: AppBar(
            title: Text('List Contacts'),
            actions: [
              IconButton(
                  icon: Icon(Icons.search),
                  tooltip: 'Search',
                  onPressed: !snapshot.hasData ? null : () {
                    showSearch(
                      context: context,
                      delegate: ContactSearch(snapshot.data),
                    );
                  }
              ),
            ],
          ),

          body: Container(
            child:
            (snapshot.hasData ?
            //Code which displays the data (works fine);
                : /* show errors/progress/etc. */),
          ),
        );
      }
  );
}
Share:
5,632
Jake Anderson
Author by

Jake Anderson

Updated on December 09, 2022

Comments

  • Jake Anderson
    Jake Anderson over 1 year

    I've been following a Flutter Search tutorial on the - boring flutter show . I have been trying to implement the same functionality using a list which is derived from a Future List where the data comes from an api (in this case and Aqueduct server).

    Currently my screen lists all the contacts from the api, i'd now like to search against that contacts list. I'm assuming it would be best practice to pass the same list (which is already being displayed) to the search delegate. Unfortunately i'm not sure how to achieve this.

    My code is as follows (please note i've stripped down some of the code for this examples):

    class _ContactsScreenState extends State<ContactsScreen> {
      static const _usersUrl = //url info;
      static final _token = //token info;
      static final _headers = {
        "Content-type" : "application/json", 
        "Accept": "application/json",
        "Authorization": "Bearer $_token",
      };
    
      HttpRequestStatus httpRequestStatus = HttpRequestStatus.NOT_DONE;
    
      Future<List<Contact>> readContacts() async {
        final response = await http.get(_usersUrl, headers: _headers);
        List responseJson = json.decode(response.body.toString());
        List<Contact> contactList = createContactList(responseJson);
        return contactList;
      }
    
      List<Contact> createContactList(List data) {
        List<Contact> list = List();
    
        for (int i = 0; i < data.length; i++) {
          String name = data[i]["name"];
          int id = data[i]["id"];
          Contact user = Contact(name: name, id: id);
          list.add(user);
        }
        return list;
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('List Contacts'),
            actions: [
              IconButton(
                icon: Icon(Icons.search),
                tooltip: 'Search',
                onPressed: (){
                   showSearch(
                     context: context,
                     delegate: ContactSearch(),
                   );
                }
              ),
            ],
          ),
    
          body: Container(
            child: FutureBuilder<List<Contact>>(
              future: readContacts(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                   //Code which displays the data (works fine);
                }
              }
            ),
          )
        )
      }
    }
    
    
    class ContactSearch extends SearchDelegate<Contact> {
      @override
      <Widget> buildActions(BuildContext context){
        //
      }
      @override
      Widget buildLeading(BuildContext context){
        //
      }
      @override
      Widget buildSuggestions(BuildContext context){
        //Pass contacts list to here and compares agains 'query' 
      }
      @override
      Widget buildResults(BuildContext context) {
        return container();
      }
    }
    

    So in brief, i need to pass the correct list/data through 'ContactSearch()':

    showSearch(
      context: context,
      delegate: ContactSearch(),
    );
    

    Thanks in advance.

  • jagdish
    jagdish almost 4 years
    wrapping scaffold in futurebuilder doesnt seems to be good idea
  • Swapnil Nakade
    Swapnil Nakade almost 4 years
    Because If somehow, snapshot will have no data it will just show a black screen which is not good thing to be showed to user i guess.
  • Herbert Poul
    Herbert Poul almost 4 years
    @SwapnilNakade what are you talking about? as you can see in the example.. you have to take care of snapshot.hasData, and display a useful progress dialog or error (snapshot.hasError) until everything is loaded.