Flutter showSearch 构建建议时的异步操作

Jak*_*kub 2 android asynchronous dart flutter

我正在使用 flutter showSearch 函数来搜索地址。到目前为止一切正常。现在我想实现每次用户更改搜索输入时都会重建的建议。为此,我使用 flutter 地理编码库。

问题是我不知道在使用 buildSuggestions 函数构建建议时如何执行异步操作。

显然我不能简单地使 buildSuggestions 函数异步,但如果可以的话我的代码将如下所示:

@override
Future<Widget> buildSuggestions(BuildContext context) async {

  var addresses = await Geocoder.local.findAddressesFromQuery(query);

  final Iterable<Address> suggestions = query.isEmpty
      ? _history
      : addresses;

  return _SuggestionList(
    query: query,
    suggestions: suggestions.map<String>((String i) => '$i').toList(),
    onSelected: (String suggestion) {
      query = suggestion;
      this.close(context, query);
    },
  );
}
Run Code Online (Sandbox Code Playgroud)

一定有办法实现我想做的事情。有什么建议么?

更新:

在 Frank06 的帖子的帮助下,我编写了以下代码:


   @override
  Widget buildSuggestions(BuildContext context) {
    return FutureBuilder(
        future: Geocoder.local.findAddressesFromQuery(query),
        builder: (BuildContext context, AsyncSnapshot<List<Address>> snapshot) {
          // check if snapshot.hasData

          if (snapshot.connectionState == ConnectionState.done) {
            List<Address> addresses;
            if (snapshot.hasData) {
              addresses = snapshot.data;
            } else {
              addresses = List<Address>();
            }

            List<String> addressNames = addresses.map((address) {
              return address.addressLine;
            }).toList();

            final Iterable<String> suggestions =
                query.isEmpty ? _history : addressNames;

            return _SuggestionList(
              query: query,
              suggestions: suggestions.map<String>((String i) => '$i').toList(),
              onSelected: (String suggestion) {
                query = suggestion;
                this.close(context, query);
              },
            );
          } else {
            return _SuggestionList(
                query: query,
                suggestions: List<String>(),
                onSelected: (String suggestion) {
                  query = suggestion;
                  this.close(context, query);
                });
          }
        });
  }
Run Code Online (Sandbox Code Playgroud)

我觉得我已经更接近解决方案了,但目前我遇到的问题是 snapshot.hasData 总是返回 false。

还有进一步的建议吗?

最终更新:

最后它确实起作用了。我的未来不会返回数据,因为我不确定我的查询实际上是字符串数据类型。下面的代码是最终的功能版本。(再次感谢 Frank06!)。

@override
 Widget buildSuggestions(BuildContext context) {
   String queryString = query;

   return FutureBuilder(
       future: queryString.length > 0 ? Geocoder.local.findAddressesFromQuery(queryString) : Future.value(List<Address>()),
       builder: (BuildContext context, AsyncSnapshot<List<Address>> snapshot) {

         if (snapshot.connectionState == ConnectionState.done) {
           List<Address> addresses;
           if (snapshot.hasData) {
             addresses = snapshot.data;
           } else {
             addresses = List<Address>();
           }

           List<String> addressNames = addresses.map((address) {
             return address.addressLine;
           }).toList();

           final Iterable<String> suggestions =
               query.isEmpty ? _history : addressNames;

           return _SuggestionList(
             query: query,
             suggestions: suggestions.map<String>((String i) => '$i').toList(),
             onSelected: (String suggestion) {
               query = suggestion;
               this.close(context, query);
             },
           );
         } else {
           return _SuggestionList(
               query: query,
               suggestions: List<String>(),
               onSelected: (String suggestion) {
                 query = suggestion;
                 this.close(context, query);
               });
         }
       });
 } 

Run Code Online (Sandbox Code Playgroud)

fra*_*k06 5

返回一个FutureBuilder

Future<Widget> buildSuggestions(BuildContext context) {
  return FutureBuilder(
    future: Geocoder.local.findAddressesFromQuery(query),
    builder: (BuildContext context, AsyncSnapshot snapshot) {
      // check if snapshot.hasData
      var addresses = snapshot.data;

      final Iterable<Address> suggestions = query.isEmpty
          ? _history
          : addresses;

      return _SuggestionList(
        query: query,
        suggestions: suggestions.map<String>((String i) => '$i').toList(),
        onSelected: (String suggestion) {
          query = suggestion;
          this.close(context, query);
        },
      );
   )
}
Run Code Online (Sandbox Code Playgroud)

FutureBuilder是建立在StatefulWidget. 尝试用 a 来解决这个问题并StatefulWidget没有,但只是级别较低且更乏味。

本文详细解释了它:https://flutterigniter.com/build-widget-with-async-method-call/

  • @Jakub 尝试 `future: Future.value([Address(), Address()])` (例如两个虚拟地址),如果这确实适用于 `snapshot.data` 那么问题就出在你的未来 (3认同)