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

Flutter中如何从ListTile获取坐标在Google Map加载所有Marker

Flutter GetX 实现客户经纬度转Google Map Marker 落地方案

核心实现逻辑

  • 客户列表数据统一存在GetX全局控制器中,跨页面直接访问,避免路由传参的序列化开销与类型错误
  • 经纬度字段提前做类型兜底转换,统一为double类型,适配Google Map组件入参要求
  • Marker生成阶段过滤非法坐标值,避免地图渲染崩溃

分步实现代码

1. 定义数据模型与GetX状态层

先统一数据结构,解决最常见的经纬度类型不匹配导致Marker不显示的问题:

import 'package:get/get.dart';

// 客户数据模型
class CustomerModel {
  final String customerName;
  final double partnerLatitude;
  final double partnerLongitude;

  CustomerModel({
    required this.customerName,
    required this.partnerLatitude,
    required this.partnerLongitude,
  });

  // 对齐原有JSON接口拉取逻辑,做类型兜底
  factory CustomerModel.fromJson(Map<String, dynamic> json) {
    return CustomerModel(
      customerName: json['partner_name'] ?? '未知客户',
      // 接口返回String/int类型都统一转double,避免类型报错
      partnerLatitude: double.tryParse(json['partner_latitude'].toString()) ?? 0,
      partnerLongitude: double.tryParse(json['partner_longitude'].toString()) ?? 0,
    );
  }
}

class CustomerController extends GetxController {
  // 响应式客户列表,和你原有拉取接口的逻辑对齐
  RxList<CustomerModel> customerList = <CustomerModel>[].obs;

  Future<void> loadCustomerData() async {
    // 保留你原有JSON接口拉取逻辑,拉取完成后给customerList赋值即可
    // 示例:
    // final apiRes = await yourCustomerApi.getList();
    // customerList.assignAll(apiRes.map((e) => CustomerModel.fromJson(e)).toList());
  }
}

注意:Google Map的LatLng构造只接受double类型入参,直接传String类型经纬度是Marker加载失败的最高发原因

2. Home页跳转逻辑

不需要把整个客户列表作为路由参数传递,直接跳转即可,全局状态跨页面可直接访问:

// Home页内跳转地图的按钮点击事件
onPressed: () {
  // 直接跳转,无需传参
  Get.to(() => const MapMarkersPage());
}

3. MapMarkers页Marker渲染逻辑

页面初始化时直接从GetX控制器取客户列表,遍历生成Marker集合:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:get/get.dart';

class MapMarkersPage extends StatefulWidget {
  const MapMarkersPage({super.key});

  @override
  State<MapMarkersPage> createState() => _MapMarkersPageState();
}

class _MapMarkersPageState extends State<MapMarkersPage> {
  late CameraPosition initialCameraPos;
  final Set<Marker> _allMarkers = {};
  // 直接获取全局已存在的客户控制器实例
  final CustomerController _customerController = Get.find<CustomerController>();

  @override
  void initState() {
    super.initState();
    _initMapConfig();
  }

  void _initMapConfig() {
    // 空列表兜底
    if (_customerController.customerList.isEmpty) {
      initialCameraPos = const CameraPosition(target: LatLng(39.90, 116.40), zoom: 12);
      setState(() {});
      return;
    }
    // 初始地图定位取第一个客户的坐标
    final firstCustomer = _customerController.customerList.first;
    initialCameraPos = CameraPosition(
      target: LatLng(firstCustomer.partnerLatitude, firstCustomer.partnerLongitude),
      zoom: 12,
    );
    // 遍历生成所有客户Marker
    for (final customer in _customerController.customerList) {
      // 过滤非法坐标,避免地图崩溃
      if (customer.partnerLatitude < -90 || customer.partnerLatitude > 90) continue;
      if (customer.partnerLongitude < -180 || customer.partnerLongitude > 180) continue;
      _allMarkers.add(
        Marker(
          // markerId必须全局唯一,重复ID会导致Marker被覆盖不显示
          markerId: MarkerId(customer.customerName),
          position: LatLng(customer.partnerLatitude, customer.partnerLongitude),
          infoWindow: InfoWindow(title: customer.customerName),
        ),
      );
    }
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('客户分布地图')),
      body: GoogleMap(
        initialCameraPosition: initialCameraPos,
        markers: _allMarkers,
        // 原有地图配置项(比如定位开关、地图样式等)可正常保留
      ),
    );
  }
}

常见问题排查

  • 确认Android端AndroidManifest.xml、iOS端Info.plist中已正确配置Google Map API Key,权限声明完整
  • 每个Marker的markerId不能重复,建议用客户唯一ID作为标识,不要用固定字符串
  • 如果页面加载后Marker为空,先打印_customerController.customerList长度,确认页面跳转前客户数据已经成功拉取赋值
  • 不要在MapMarkers页重复调用Get.put(CustomerController()),会重新创建空的控制器实例,导致拿不到已有客户数据,统一用Get.find()获取已初始化的实例

内容的提问来源于stack exchange,提问作者Zakaria Hamid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:07:04