【问题标题】:SearchDelegate with ChangeNotifier + ProviderSearchDelegate 与 ChangeNotifier + Provider
【发布时间】:2019-08-23 00:52:45
【问题描述】:

如何正确使用ChangeNotifierSearchDelegate

我有一些看起来像这样的东西:

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 添加一个侦听器?

我正在使用提供者来注入我的SearchNotifier,所以无论在哪里调用search,我们都需要访问上下文。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    我通过直接从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

    【讨论】:

      【解决方案2】:

      我做了不同的事情,但我也在我的应用程序中使用了提供程序。所以我的自定义搜索委托看起来像这样:

       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(),
              );
            },
          );
        }
      }
      

      希望这会有所帮助。如果有不清楚的地方,请告诉我。谢谢!

      【讨论】:

      • 在这个解决方案中,GlobalModel 是否在任何步骤中调用notifyListeners?我遇到的问题是我会在buildSuggestions 内调用GlobalModel.searchsearch 调用外部 API 并最终调用 notifyListeners,导致再次调用 buildSuggestions 并重复循环。在查看您的解决方案后,它给了我一个关于如何修改我的代码来解决问题的提示。我很快就会在这里发布解决方案。
      • 点击按钮时会调用showSearch,因此即使在某些地方调用了notifyListeners而重新创建了小部件,也不会再次调用showSearch,因此不会调用两次buildSuggestions或buildResults。在我的情况下,notifyListeners 在我用于 buildSuggestions 和 buildResults 的小部件内被调用,并且它可以正常工作。
      猜你喜欢
      • 2020-05-29
      • 1970-01-01
      • 2020-11-03
      • 2020-11-23
      • 2020-05-31
      • 2020-12-17
      • 2020-12-02
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多