如何在SearchDelegate中正确使用ChangeNotifier
我有一个类似这样的东西:
class SearchNotifier with ChangeNotifier {
List<String> results;
Future<void> search(String query) async {
results = await API.search(query);
notifyListeners();
}
}在我的SearchDelegate中
Widget buildSuggestions(BuildContext context) {
final searchNotifier = Provider.of<SearchNotifier>(context);
searchNotifier.search(query);
...
}当结果更新时,SearchNotifier更新其侦听器,重新构建SearchDelegate,调用buildSuggestions,然后再次调用search,进入循环。
有没有一种方法可以在searchNotifier.search(query)方法之外进行构建?也许我可以在SearchDelegate _queryTextController中添加一个监听器
我使用provider来注入我的SearchNotifier,所以无论在哪里调用search,我们都需要访问上下文。
发布于 2019-08-26 22:58:21
我通过直接从search方法返回搜索结果,然后使用FutureBuilder解决了这个问题。
class SearchNotifier with ChangeNotifier {
Future<List<String>> search(String query) async {
return await API.search(query);
}
}
Widget buildSuggestions(BuildContext context) {
final searchNotifier = Provider.of<SearchNotifier>(context);
results = searchNotifier.search(query);
// FutureBuilder on results
...
}SearchNotifier不再需要成为ChangeNotifier,因为问题的根源是notifyListeners。
发布于 2019-08-24 16:07:19
我做的不同,但我也在我的应用程序中使用提供者。因此,我的自定义搜索委托如下所示:
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;
}
}我的ExerciseList是这样的:
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(),
);
},
);
}
}希望这能有所帮助。如果有什么不清楚的地方,请告诉我。谢谢!
https://stackoverflow.com/questions/57618579
复制相似问题