Flutter:如何使用 Getx Obx 更新标记在谷歌地图中的位置?

Posted

技术标签:

【中文标题】Flutter:如何使用 Getx Obx 更新标记在谷歌地图中的位置?【英文标题】:Flutter: How do I update markers' position in google map using Getx Obx? 【发布时间】:2021-12-27 15:09:29 【问题描述】:

我有关注view

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

class MapViewerPage extends StatelessWidget 
  MapViewerPage(Key? key) : super(key: key);

  final MapViewController mapcontroller = MapViewController();
  final Completer<GoogleMapController> _controller = Completer();
  final CameraPosition _initialCameraPosition = const CameraPosition(
    target: LatLng(28.527582, 77.0688971),
    zoom: 16,
  );

  final BitmapDescriptor defaultIcon =
      BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed);

  final List<Marker> allMarkers = [];

  @override
  Widget build(BuildContext context) 
    return GetBuilder<MapViewController>(
        init: mapcontroller,
        builder: (controller) 
           return SizedBox(
              width: double.infinity,
              height: double.infinity,
              child: Obx(() => GoogleMap(
            myLocationButtonEnabled: true,
            markers:Set<Marker>.of(allMarkers),
            mapType: MapType.normal,
            initialCameraPosition: _initialCameraPosition,
            onMapCreated: (GoogleMapController gmcontroller) 
              _controller.complete(gmcontroller);
              gmcontroller.setMapStyle(controller.loadMapStyle());
            ,
          )),
            ),
        );
  

  getMarkers() 
    //get markers from controller
    var realdata = mapcontroller.realtimeList;

    realdata.asMap().forEach((key, value) 
      var _marker = Marker(
          consumeTapEvents: true,
          markerId: MarkerId(key.toString()),
          position: LatLng(
              double.parse(value.latitude), double.parse(value.longitude)),
          onTap: () 
            //do something here
          );

      allMarkers.add(_marker);
    );
  

我的控制器看起来像这样。

import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../Models/model_realtime.dart';
import '../../Providers/common_api_provider.dart';

class MapViewController extends GetxController 
  var isLoading = false.obs;
  var realtimeList = <ModelRealtime>[].obs;

  @override
  void onInit() 
    fetchRealtimeData();
    super.onInit();
  

  void fetchRealtimeData() async 
    try 
      isLoading(true);
      var realtime = await CommonApiProvider.realTimeData();
      if (realtime != null) 
        realtimeList.value = realtime;
      
     catch (e) 
      isLoading(false);
      // ignore: avoid_print
      print(e);
      rethrow;
     finally 
      isLoading(false);
    
  

  loadMapStyle() async 
    String style = await rootBundle.loadString("assets/map_style.json");
    return style;
  

这些代码运行良好,但似乎每次新数据到达时都会重新加载/刷新 Googlemap。如何仅在每次在数据库中更新新的纬度、经度时才更新标记的位置,而无需重新加载/刷新 Googlemap?

谢谢

【问题讨论】:

【参考方案1】:

您正在视图内初始化 allMarkers 列表,这就是为什么您需要手动刷新页面才能在地图上显示标记。

MapViewController中初始化allMarkers

List&lt;Marker&gt; allMarkers = &lt;Marker&gt;[].obs; // Inside Map View Controller

然后,在 Google 地图小部件中替换标记属性

Obx(() => GoogleMap(
            myLocationButtonEnabled: true,
            markers:Set<Marker>.of(controller.allMarkers), // <====== Update
            mapType: MapType.normal,
            initialCameraPosition: _initialCameraPosition,
            onMapCreated: (GoogleMapController gmcontroller) 
              _controller.complete(gmcontroller);
              gmcontroller.setMapStyle(controller.loadMapStyle());
            ,
          ))

getMarkers函数中

getMarkers() 
    // Add this line. Create map view controller object
    final MapViewController _controller = Get.find(); // <======= Add
    //get markers from controller
    var realdata = mapcontroller.realtimeList;

    realdata.asMap().forEach((key, value) 
      var _marker = Marker(
          consumeTapEvents: true,
          markerId: MarkerId(key.toString()),
          position: LatLng(
              double.parse(value.latitude), double.parse(value.longitude)),
          onTap: () 
            //do something here
          );

      _controller.allMarkers.add(_marker); // <===== Update
      _controller.update() // <=== Add, because you are using GetBuilder
    );
  

【讨论】:

感谢您的回复! Obx( () -&gt; GoogleMap (... 不会在每次出现新的标记数据时刷新/重新加载 Googlemap? 如果我在控制器本身上移动getMarkers() 方法呢? @WatsMyName 实际上,您不需要将 Google 地图小部件包装在 Obx 中,因为 Google 地图已经包装在 Get 构建器中,因此在此阶段使用 Obx 是不必要的,是的,只要构建器收到更改,它就会重新渲染是孩子 @WatsMyName 在控制器中移动 getMarkers 是一种推荐的方式。如果您有特定屏幕的控制器,那么您应该在控制器内编写与屏幕相关的所有功能 没有办法防止重新渲染谷歌地图吗?更改仅发生在 Marker 的位置,因此重新渲染整个地图不是一个好主意。我认为每次重新加载地图时谷歌都会收取费用。

以上是关于Flutter:如何使用 Getx Obx 更新标记在谷歌地图中的位置?的主要内容,如果未能解决你的问题,请参考以下文章

我正在使用 Getx 进行状态管理,当我将数据添加到服务器时,它不会在列表视图中出现更新的数据,直到热重启而列表视图位于 Obx 中

使用 Obx,得到这个错误:[Get] 检测到 GetX 使用不当

使用 GetX 可观察对象时,哪些 UI 小部件需要包装在 Obx 中?

Flutter之GetX入门指南 ObxWidget原理剖析

Flutter之GetX入门指南 ObxWidget原理剖析

Getx:通过其他类的obs值触发man类中的obx