【发布时间】:2021-08-20 01:42:38
【问题描述】:
我有大量的 json 数据,我正在从资产中加载这些数据。我需要使用 recipeName 从食谱中进行搜索,并且我正在使用 flutter typeahead 创建搜索栏和功能。
应用启动时,我正在加载所有配方对象。下面的代码基本上返回了所有的菜谱。
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;
}
这段代码负责搜索(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;
}
}
现在是预输入部分。 Flutter typeahead 需要 4 个参数
textFieldConfiguration、suggestionsCallback、itemBuilder、onSuggestionSelected
对于SuggestionsCallback,当屏幕加载并从该列表中搜索时,我将所有食谱名称加载到列表中:
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();
}
这是整个 typeahead 小部件:
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),
);
},
),
);
}
如您所见,我正在使用上述类进行临时搜索。现在对于openSuggestionsSelected,我必须将用户发送到recipeDetailsScreen,它接受RecipeModel 的对象。
-
我一直在想,虽然我要进行临时搜索,但我可以在一定程度上减少混乱吗?我的意思是除了加载商店中所有食谱的功能外,我还有两个列表可以工作。一个带有食谱的名称,一个带有所有食谱。有没有办法使用一个列表来做到这一点?
-
我可以提高搜索效率吗?我不认为使用两个列表是一个好主意。
N.B:我编写的解决方案有效。我只需要一些可以消除混乱并希望降低搜索时间复杂度或至少提高功能效率的东西。
【问题讨论】:
-
Hi 实际上是在寻找一些非常简单的东西来实现负责返回对象的搜索功能。我想实现 trie 会花费很多时间?
-
不用实现,已经有a package that does that for you了。它甚至针对自动完成任务进行了优化。
-
您熟悉预输入吗?我需要返回一个对象。看了包我觉得不行吗?
-
您阅读过
trie文档吗?只需使用getAllWordsWithPrefix方法将query传递给它并在suggestionsCallback中返回它,例如trie.getAllWordsWithPrefix(query).