Flutter 带有ChangeNotifier+提供程序的SearchDelegate
如何将ChangeNotifier与SearchDelegate一起正确使用 我有一些东西看起来像这样:Flutter 带有ChangeNotifier+提供程序的SearchDelegate,flutter,Flutter,如何将ChangeNotifier与SearchDelegate一起正确使用 我有一些东西看起来像这样: class ExerciseSearchDelegate extends SearchDelegate { @override List<Widget> buildActions(BuildContext context) { return [ IconButton( icon: Icon(Icons.clear),
class ExerciseSearchDelegate extends SearchDelegate {
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
@override
Widget buildResults(BuildContext context) {
// ExeciseList is a widget which accepts a query as optional parameter
return ExerciseList(
query: query,
);
}
@override
Widget buildSuggestions(BuildContext context) {
return Column();
}
@override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
}
class ExerciseList extends StatelessWidget {
final String query;
const ExerciseList({this.query, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _model = Provider.of<GlobalModel>(context);
List<ExerciseModel> _results = query != null
? _model.exercises
.where((ex) => ex.name.toLowerCase().contains(query.toLowerCase()))
.toList()
: _model.exercises;
return ListView.builder(
itemCount: _results.length,
itemBuilder: (context, position) {
var exercise = _results[position];
return MultiProvider(
providers: [
ChangeNotifierProvider.value(notifier: exercise),
],
child: ExerciseListItem(),
);
},
);
}
}
使用ChangeNotifier类SearchNotifier{
列出结果;
未来搜索字符串查询异步{
结果=等待API.searchquery;
通知听众;
}
}
在我的发言中:
Widget BuildSuggestionBuildContext上下文{
final searchNotifier=Provider.ofcontext;
searchNotifier.searchquery;
...
}
当结果更新时,SearchNotifier更新其侦听器,SearchDelegate被重建,buildSuggestions被调用,search被再次调用,进入循环
是否有一种在生成方法之外执行searchNotifier.searchquery的方法?也许我可以在SearchDelegate\u queryTextController中添加一个侦听器
我正在使用提供程序注入我的SearchNotifier,因此无论在哪里调用搜索,我们都需要访问上下文。我做了不同的选择,但我也在我的应用程序中使用提供程序。因此,我的自定义搜索委托如下所示:
class ExerciseSearchDelegate extends SearchDelegate {
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
@override
Widget buildResults(BuildContext context) {
// ExeciseList is a widget which accepts a query as optional parameter
return ExerciseList(
query: query,
);
}
@override
Widget buildSuggestions(BuildContext context) {
return Column();
}
@override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
}
class ExerciseList extends StatelessWidget {
final String query;
const ExerciseList({this.query, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _model = Provider.of<GlobalModel>(context);
List<ExerciseModel> _results = query != null
? _model.exercises
.where((ex) => ex.name.toLowerCase().contains(query.toLowerCase()))
.toList()
: _model.exercises;
return ListView.builder(
itemCount: _results.length,
itemBuilder: (context, position) {
var exercise = _results[position];
return MultiProvider(
providers: [
ChangeNotifierProvider.value(notifier: exercise),
],
child: ExerciseListItem(),
);
},
);
}
}
我的练习表如下所示:
class ExerciseSearchDelegate extends SearchDelegate {
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
close(context, null);
},
);
}
@override
Widget buildResults(BuildContext context) {
// ExeciseList is a widget which accepts a query as optional parameter
return ExerciseList(
query: query,
);
}
@override
Widget buildSuggestions(BuildContext context) {
return Column();
}
@override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
}
class ExerciseList extends StatelessWidget {
final String query;
const ExerciseList({this.query, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
final _model = Provider.of<GlobalModel>(context);
List<ExerciseModel> _results = query != null
? _model.exercises
.where((ex) => ex.name.toLowerCase().contains(query.toLowerCase()))
.toList()
: _model.exercises;
return ListView.builder(
itemCount: _results.length,
itemBuilder: (context, position) {
var exercise = _results[position];
return MultiProvider(
providers: [
ChangeNotifierProvider.value(notifier: exercise),
],
child: ExerciseListItem(),
);
},
);
}
}
希望这有帮助。如果有什么不清楚的,请告诉我。谢谢大家! 我通过直接从搜索方法返回搜索结果,然后使用FutureBuilder解决了这个问题 使用ChangeNotifier类SearchNotifier{ 未来搜索字符串查询异步{ 返回等待API.searchquery; } } Widget BuildSuggestionBuildContext上下文{ final searchNotifier=Provider.ofcontext; 结果=searchNotifier.searchquery; //基于结果的未来建设者 ... }
SearchNotifier不再需要是ChangeNotifier,因为问题的根源是notifyListeners。在此解决方案中,GlobalModel是否在任何步骤中调用notifyListeners?我遇到的问题是,我会在buildSuggestions中调用GlobalModel.search。search调用外部API并最终调用notifyListeners,导致再次调用buildSuggestions,循环将重复。在查看了您的解决方案之后,它给了我一个关于如何修改代码以解决问题的提示。我很快会在这里发布解决方案。单击按钮时会调用showSearch,因此即使由于在某些地方调用了notifyListeners而重新创建了小部件,也不会再次调用showSearch,因此不会调用两次buildSuggestions或buildResults。在我的例子中,notifyListeners是在我用于buildSuggestions和buildResults的小部件中调用的,它可以正常工作。