You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 17:50:24