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

Flutter Google Maps场景下多类中Future的正确处理方法

解决Dart异步初始化导致的经纬度Null问题

你的问题核心在于构造函数是同步执行的,但获取位置是异步操作——当MapsService的构造函数执行到CameraPosition赋值时,LocationInfo里的latitude和longitude还没被异步回调赋值,自然是null,最终引发崩溃。下面是具体的重构方案:

第一步:重构LocationInfo,将异步逻辑移出构造函数

Dart的类构造函数不能是async的,所以我们把位置获取的逻辑放到一个单独的异步初始化方法中,或者用工厂构造函数直接返回Future<LocationInfo>:

class LocationInfo {
  Location location = Location();
  LocationData? currentLocation;
  double? longitude;
  double? latitude;

  // 空的默认构造函数
  LocationInfo();

  // 异步初始化方法
  Future<void> init() async {
    try {
      final locationData = await location.getLocation();
      currentLocation = locationData;
      longitude = currentLocation?.longitude;
      latitude = currentLocation?.latitude;
    } catch (e) {
      currentLocation = null;
      longitude = null;
      latitude = null;
    }
  }

  // 可选:用工厂构造函数直接返回初始化完成的实例
  factory LocationInfo.create() async {
    final info = LocationInfo();
    await info.init();
    return info;
  }
}

第二步:修改MapsService,等待位置初始化完成再创建相机位置

同样,MapsService的构造函数也不能是async的,我们用工厂构造函数+私有异步初始化方法的组合,确保等待LocationInfo完成初始化后再赋值CameraPosition:

class MapsService {
  bool loading = false;
  LocationInfo? locationInfo;
  CameraPosition? cameraPosition;

  // 工厂构造函数,返回Future<MapsService>
  factory MapsService.create() async {
    final service = MapsService();
    await service._init();
    return service;
  }

  // 私有异步初始化方法
  Future<void> _init() async {
    loading = true;
    // 方式1:用init方法
    locationInfo = LocationInfo();
    await locationInfo!.init();

    // 方式2:用LocationInfo的工厂构造函数
    // locationInfo = await LocationInfo.create();

    // 给经纬度加默认值,避免获取失败时出现null
    cameraPosition = CameraPosition(
      zoom: 15,
      target: LatLng(
        locationInfo?.latitude ?? 0.0, 
        locationInfo?.longitude ?? 0.0
      ),
    );
    loading = false;
  }
}

第三步:使用MapsService的正确方式

现在不能直接用MapsService()创建实例,必须通过await MapsService.create()来获取初始化完成的对象。如果是在Flutter UI中使用,建议配合FutureBuilder处理异步状态:

FutureBuilder<MapsService>(
  future: MapsService.create(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: CircularProgressIndicator());
    } else if (snapshot.hasError) {
      return Center(child: Text('获取位置失败:${snapshot.error}'));
    } else {
      final mapsService = snapshot.data!;
      return GoogleMap(
        initialCameraPosition: mapsService.cameraPosition!,
        // 其他地图配置...
      );
    }
  },
)

关键说明

  • 永远不要在同步构造函数里依赖异步回调的结果——回调会在构造函数执行完之后才触发,导致变量未初始化。
  • 添加默认值(?? 0.0)是为了处理位置获取失败的极端情况,避免即使等待完成后依然出现null的问题。

内容的提问来源于stack exchange,提问作者Ozan Taskiran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:13:04