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

Flutter集成Google Maps如何传入Firebase经纬度实现位置追踪

实现方案

整个流程没有特殊逻辑,拆成「环境配置→Firebase数据实时拉取→地图点位渲染与更新」三个环节,按下面步骤写就能跑通。

第一步:前置依赖配置
  • 在项目pubspec.yaml文件中添加必须的依赖,版本号可根据你本地Flutter SDK版本做兼容调整,不需要硬追最新版:
dependencies:
  flutter:
    sdk: flutter
  google_maps_flutter: ^2.5.0 # 谷歌地图官方Flutter插件
  firebase_core: ^2.24.2 # Firebase核心初始化库
  cloud_firestore: ^4.14.0 # 若使用Firestore存储位置则引入,用Realtime Database替换为对应插件即可
  • 完成基础配置:关联Flutter项目与你的Firebase项目,在安卓、iOS端分别配置Google Maps API Key,若需要同时追踪设备自身位置,记得添加精确定位权限声明。
第二步:从Firebase拉取经纬度数据

首先统一Firebase端的数据存储格式:存储位置的文档/节点下,latitude(纬度)、longitude(经度)字段必须为数值类型,不要存为字符串,避免后续类型转换报错。
做位置追踪建议用实时监听的方式拉取数据,不需要手动反复请求,数据更新时自动触发回调即可,示例代码如下:

// 存储从Firebase拿到的目标位置
LatLng? _trackedLocation;
// 地图控制器实例,后续用来操作地图视角
GoogleMapController? _mapController;
final FirebaseFirestore _db = FirebaseFirestore.instance;

@override
void initState() {
  super.initState();
  // 监听位置对应文档的实时变化,示例路径替换成你自己Firebase中的存储路径
  _db.collection('location_records').doc('target_device_01').snapshots().listen((snapshot) {
    if (!snapshot.exists) return;
    final locationData = snapshot.data() as Map<String, dynamic>;
    // 做类型兼容:如果经纬度是int类型,自动转成double避免类型错误
    final lat = (locationData['latitude'] as num).toDouble();
    final lng = (locationData['longitude'] as num).toDouble();
    
    setState(() {
      _trackedLocation = LatLng(lat, lng);
    });

    // 数据更新后自动移动地图视角到新位置
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_mapController != null && _trackedLocation != null) {
        _mapController!.animateCamera(
          CameraUpdate.newLatLng(_trackedLocation!)
        );
      }
    });
  });
}

如果你使用Firebase Realtime Database存储位置,逻辑完全一致,只需要把数据监听的API替换为Realtime Database对应的监听方法即可,核心逻辑都是拿到经纬度数值后转成Flutter谷歌插件认可的LatLng对象。

第三步:Google Maps点位渲染

注意不要在位置数据未加载完成时强行渲染标记,避免空指针错误,示例代码如下:

// 地图默认初始点位,数据加载完成前先显示这个位置
final CameraPosition _defaultInitPosition = const CameraPosition(
  target: LatLng(39.9042, 116.4074),
  zoom: 15,
);

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('位置追踪')),
    body: Stack(
      children: [
        GoogleMap(
          initialCameraPosition: _defaultInitPosition,
          onMapCreated: (controller) {
            _mapController = controller;
          },
          // 传入要显示的标记集合
          markers: _trackedLocation == null
            ? const <Marker>{}
            : {
                Marker(
                  markerId: const MarkerId('tracked_target'),
                  position: _trackedLocation!, // 直接传入从Firebase拿到的经纬度对象
                  infoWindow: const InfoWindow(title: '追踪目标'),
                )
              },
          // 打开我的位置图层需要先申请定位权限
          myLocationEnabled: true,
        ),
        // 数据未加载时显示加载态
        if (_trackedLocation == null)
          const Center(child: CircularProgressIndicator())
      ],
    ),
  );
}
常见踩坑说明
  • 不要每次位置更新就重新创建整个GoogleMap组件,只需要更新markers集合、调用相机移动方法即可,否则会出现地图闪烁、卡顿问题。
  • 所有涉及GoogleMapController的操作,必须加非空判断,等onMapCreated回调执行完成后再调用控制器方法,避免空指针。
  • 经纬度取值范围不要写错:纬度范围是-90到90,经度范围是-180到180,传错值会导致地图加载报错。
  • 如果需要同时展示多个位置点,只需要把从Firebase拿到的多个经纬度转成Marker对象,放进markers集合即可,逻辑和单个点位完全一致。

内容的提问来源于stack exchange,提问作者Arevan Shamal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:45:46