I have a huge json data which I'm loading from assets. I need to search from the recipe's using recipeName and I'm using flutter typeahead to create the search bar and functionalities.
I'm loading all the recipe objects when the app starts. The below code basically returns all the recipes.
List<RecipeModel> getAllRecipes() {
for (int i = 0; i < _appData.recipeCategories!.length; i++) {
for (int j = 0; j < _appData.recipeCategories![i].recipes!.length; j++) {
_recipeList.add(_appData.recipeCategories![i].recipes![j]);
}
}
return _recipeList;
}
This code is responsible for the search(Search.dart):
class Search {
List<RecipeModel> _recipeList = Store.instance.getAllRecipes(); // Store loads data during splash screen
late RecipeModel recipe;
RecipeModel returnRecipe(String? suggestion) {
for (int i = 0; i < _recipeList.length; i++) {
if (suggestion == _recipeList[i].recipeName) {
return _recipeList[i];
}
}
return recipe;
}
}
And now comes the typeahead part. Flutter typeahead takes 4 parameter
textFieldConfiguration
, suggestionsCallback
, itemBuilder
, onSuggestionSelected
for suggestionsCallback I'm loading all the recipenames into a list when the screen loads and searching from that list using:
Future<List<String>> getSuggestions(String str) async {
return List.of(recipeNamesList).where(
(recipe) {
final recipeLower = recipe.toLowerCase();
final queryLower = str.toLowerCase();
return recipeLower.contains(queryLower);
},
).toList();
}
and here's the entire typeahead widget:
Widget buildSearchTextInput() {
return Container(
padding: EdgeInsets.all(10),
child: TypeAheadFormField<String?>(
textFieldConfiguration: TextFieldConfiguration(
controller: _textEditingController,
focusNode: _focusNode,
autofocus: true,
decoration: InputDecoration(
hintText: "Enter recipe name",
),
),
suggestionsCallback: (query) async {
print("query: $query");
if (query.length == 0) return [];
return await getSuggestions(query);
},
hideOnEmpty: true,
itemBuilder: (context, String? suggestion) =>
SearchResultCard(suggestion: suggestion),
onSuggestionSelected: (String? suggestion) {
openRecipeDetailsPage(
context,
Search().returnRecipe(suggestion),
);
},
),
);
}
As you can see I'm using the afore mentioned class for a ad-hoc search. Now for openSuggestionsSelected
I have to send the user to a recipeDetailsScreen
which takes a object of RecipeModel
.
I was thinking all though I'm going ad-hoc search for this can I reduce the clutter to some extent? I mean apart from the function to load all the recipes in store I have two list to work one. One carries names of the recipes and one carries the all the recipes. Is there a way I can do it using one list?
Can I improve the efficiency for the search? I don't think working with two list is a good idea.
N.B: The solution I've written works. I just need something that'll remove the clutter and hopefully reduce the time complexity of the search or at the very least improve functional efficiency.