Dart 2.18.1中Future类型不匹配错误:Object无法转为Future<Iterable<Suggestion>>
解决Flutter地图项目中TypeAheadField回调的类型不匹配错误
问题场景
使用启用空安全的Dart 2.18.1,通过Android Studio开发Flutter地图项目时,在maps_screen.dart的TypeAheadField组件suggestionsCallback回调中调用PlacesAPIProvider.fetchSuggestions方法,出现类型不匹配的编译错误,导致构建失败。
错误日志
lib/maps_screen.dart:84:26: Error: A value of type 'Object' can't be returned from an async function with return type 'Future<Iterable<Suggestion>>'. - 'Object' is from 'dart:core'. - 'Future' is from 'dart:async'. - 'Iterable' is from 'dart:core'. - 'Suggestion' is from 'package:gmapsdemo/places_api.dart' ('lib/places_api.dart'). return await PlacesAPIProvider('23456') ^ FAILURE: Build failed with an exception. * Where: Script 'C:\Users\induw\Documents\flutter\Flutter\flutter_windows_3.3.2-stable\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 1159 * What went wrong: Execution failed for task ':app:compileFlutterBuildDebug'. > Process 'command 'C:\Users\induw\Documents\flutter\Flutter\flutter_windows_3.3.2-stable\flutter\bin\flutter.bat'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 1m 42s Exception: Gradle task assembleDebug failed with exit code 1
相关代码
maps_screen.dart
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:geolocator/geolocator.dart'; import 'package:gmapsdemo/places_api.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class MapsScreen extends StatefulWidget { MapsScreen({Key? key}) : super(key : key); @override _MapsScreenState createState() => _MapsScreenState(); } class _MapsScreenState extends State<MapsScreen> { final Completer<GoogleMapController> _controller = Completer(); static const LatLng _initialPosition = LatLng(6.8747747, 79.8645194); final Set<Marker> _markers = {}; late LatLng user_current_position; MapType currentMapType = MapType.normal; TextEditingController _addressController = TextEditingController(); void _onMapCreate(GoogleMapController controller) { _controller.complete(controller); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Map Screen'), ), body: Stack( children: [ Container( child: GoogleMap( onMapCreated: _onMapCreate, initialCameraPosition: CameraPosition(target: _initialPosition, zoom: 9), markers: _markers, onTap: (latLng){ _onAddMaker(latLng); }, mapType: currentMapType, ), ), Positioned( child: Container( margin: EdgeInsets.only(top: 10, left: 10, right: 10), height: 50, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), spreadRadius: 3, blurRadius: 2,) ]), child: TypeAheadField<Suggestion>( textFieldConfiguration: TextFieldConfiguration( controller: _addressController, decoration: InputDecoration( alignLabelWithHint: true, hintText: 'Type Address', border: InputBorder.none, hintStyle: TextStyle(fontSize: 20), isCollapsed: true), ), hideOnEmpty: true, hideOnLoading: true, suggestionsCallback: (pattern) async { return //await PlacesAPIProvider('23456') .fetchSuggestions(pattern);// }, itemBuilder: (context, suggestion) { return GestureDetector( onTap: (){}, child: ListTile( title: Text(suggestion.description, style: TextStyle(color: Colors.black)), ), ); }, onSuggestionSelected: (selectedSuggestion) {}, ), ), ), Positioned( bottom: 8, left: 8, child: FloatingActionButton( child: Icon( Icons.my_location, color: Colors.white, ), onPressed: () async{ await getUserCurrentPosition().then((value) async{ await _navigateCameraToPosition(value); }); }, )), Positioned( bottom: 8, left: 80, child: FloatingActionButton( child: Icon( Icons.map, color: Colors.white, ), onPressed: (){ setState(() { currentMapType = (currentMapType == MapType) ? MapType.satellite : MapType.normal; }); }, )) ], ), ); } void _onAddMaker(LatLng position) { setState(() { _markers.add( Marker( icon: BitmapDescriptor.defaultMarker, markerId: MarkerId(position.longitude.toString()), position: position, infoWindow: InfoWindow( title: "Maker", snippet: position.toString()) ) ); }); } Future<LatLng> getUserCurrentPosition() async { var position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.best ); setState(() { user_current_position = LatLng(position.latitude, position.longitude); }); return user_current_position; } Future _navigateCameraToPosition(LatLng position) async { final controller = await _controller.future; await controller.animateCamera(CameraUpdate.newCameraPosition( CameraPosition(target: position , zoom: 12) )); } }
places_api.dart
import 'dart:convert'; import 'package:http/http.dart' as http; class PlacesAPIProvider{ final sessionToken; PlacesAPIProvider(this.sessionToken); final apiKey = 'API_KEY'; Future<Object> fetchSuggestions(String query) async { if( query.isNotEmpty){ final request = 'https://maps.googleapis.com/maps/api/place/autocomplete/json' 'input=$query&types=address&language=en&components=cpuntry:sl' '&key=$apiKey&sessointoken=$sessionToken'; final response = await http.get(Uri.parse(request)); if(response.statusCode == 200) { final result = json.decode(response.body); if (result['status'] == 'ok') { return result['predications'] .map<Suggestion>( (p) => Suggestion( p['place_id'], p['description'])) .toList(); }else{ return []; } } else{ return []; } } else{ return []; } return ''; } } class Suggestion{ final String placeId; final String description; Suggestion( this.placeId , this.description); }
解决方案
1. 修正fetchSuggestions方法的返回类型与逻辑
places_api.dart中fetchSuggestions的返回类型被定义为Future<Object>,但实际需要返回Suggestion列表,导致类型不匹配。同时存在拼写错误,需一并修正:
import 'dart:convert'; import 'package:http/http.dart' as http; class PlacesAPIProvider{ final sessionToken; PlacesAPIProvider(this.sessionToken); final apiKey = 'API_KEY'; // 修改返回类型为Future<List<Suggestion>> Future<List<Suggestion>> fetchSuggestions(String query) async { if (query.isNotEmpty) { // 修正API请求中的拼写错误:cpuntry→country,sessointoken→sessiontoken,添加?分隔路径和参数 final request = 'https://maps.googleapis.com/maps/api/place/autocomplete/json' '?input=$query&types=address&language=en&components=country:sl' '&key=$apiKey&sessiontoken=$sessionToken'; final response = await http.get(Uri.parse(request)); if (response.statusCode == 200) { final result = json.decode(response.body); // 谷歌API返回的status是大写OK,修正为'OK' if (result['status'] == 'OK') { // 修正字段名predications→predictions return result['predictions'] .map<Suggestion>( (p) => Suggestion(p['place_id'], p['description'])) .toList(); } } } // 所有分支统一返回空列表,移除多余的return ''分支 return []; } } class Suggestion{ final String placeId; final String description; Suggestion( this.placeId , this.description); }
2. 修正maps_screen.dart中的回调调用
移除suggestionsCallback中的错误注释,正确调用方法:
suggestionsCallback: (pattern) async { return await PlacesAPIProvider('23456').fetchSuggestions(pattern); },
3. 修复地图类型切换逻辑
修正地图类型判断的错误,将currentMapType == MapType改为和具体枚举值比较:
onPressed: (){ setState(() { currentMapType = (currentMapType == MapType.normal) ? MapType.satellite : MapType.normal; }); },
说明
以上修改解决了类型不匹配的核心问题,同时修复了API请求中的拼写错误和逻辑错误,确保代码符合空安全要求并能正常编译运行。
内容的提问来源于stack exchange,提问作者induwara widarshana
相关产品推荐
相关产品推荐

