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
相关产品推荐
相关产品推荐

