SearchDelagate displaying duplicate results

Viewed 146

i am using search delegate to implement search function. Using API to fetch data, everything seems to be working fine, only problem is that every time i type a letter, list seems to rebuild and shows duplicate result.

Below is the code for search delegate class. enter image description here

All your help will be very useful. Thanks in advance.

  class SearchBar extends SearchDelegate {
  List<LeadModel> names = [];
  List recentSearch = [];

  getNames() async {
    http
        .get(
      Uri.https('jsonplaceholder.typicode.com', 'users'),
    )
        .then((data) {
      return json.decode(data.body);
    }).then((data) {
      for (var json in data) {
        names.add(LeadModel.fromJson(json));
      }
      print(names.length);
    }).catchError((e) {
      print(e);
    });
  }

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          onPressed: () {
            query = '';
          },
          icon: Icon(Icons.clear))
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        onPressed: () {
          close(context, '');
        },
        icon: Icon(Icons.arrow_back));
  }

  @override
  Widget buildResults(BuildContext context) {
    return Container();
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final suggestions = names.where((name) {
      return name.name.toLowerCase().contains(query.toLowerCase());
    });
    return FutureBuilder(
      future: getNames(),
      builder: (context, snapshot) {
        if (query.isEmpty) return Center(child: Text(""));
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return Center(child: Text(""));
          default:
            if (snapshot.hasError) {
              return Center(child: Text(""));
            } else {
              names.clear();
              return ListView.builder(
                itemCount: suggestions.length,
                itemBuilder: (context, i) {
                  return ListTile(
                    title: Text(suggestions.elementAt(i).name),
                  );
                },
              );
            }
        }
      },
    );
  }
}
2 Answers

In your getNames functions, clear the list names before adding items to it, like this:

getNames() async {
   
   names.clear();
   
   await http
        .get(
      Uri.https('jsonplaceholder.typicode.com', 'users'),
    )

fixed it with the help from @Huthaifa Muayyad, working code is

class SearchBar extends SearchDelegate {
  List<LeadModel> names = [];
  List recentSearch = [];

  getNames() async {
    names.clear();
    await http
        .get(
      Uri.https('jsonplaceholder.typicode.com', 'users'),
    )
        .then((data) {
      return json.decode(data.body);
    }).then((data) {
      for (var json in data) {
        names.add(LeadModel.fromJson(json));
      }
      print(names.length);
    }).catchError((e) {
      print(e);
    });
  }

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          onPressed: () {
            query = '';
          },
          icon: Icon(Icons.clear))
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        onPressed: () {
          close(context, '');
        },
        icon: Icon(Icons.arrow_back));
  }

  @override
  Widget buildResults(BuildContext context) {
    return Container();
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final suggestions = names.where((name) {
      return name.name.toLowerCase().contains(query.toLowerCase());
    });
    return FutureBuilder(
      future: getNames(),
      builder: (context, snapshot) {
        if (query.isEmpty) return Center(child: Text(""));
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return Center(child: Text(""));
          default:
            if (snapshot.hasError) {
              return Center(child: Text(""));
            } else {
              return ListView.builder(
                itemCount: suggestions.length,
                itemBuilder: (context, i) {
                  return ListTile(
                    title: Text(suggestions.elementAt(i).name),
                  );
                },
              );
            }
        }
      },
    );
  }
}
Related