Flutter: How do I update markers' position in google map using Getx Obx?

Viewed 1946

I have following 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);
    });
  }
}

And my controller looks like this.

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;
  }
}

These codes work pretty well, but it seems to reload/refresh Googlemap everytime new data arrives. How do I update markers' position only everytime the new latitude, longitude updated in the database without reloading/refreshing Googlemap?

Thanks

1 Answers

You are initializing allMarkers list inside view, that's why you need to manually refresh the page in order to display markers on the map.

Initialize allMarkers inside MapViewController

List<Marker> allMarkers = <Marker>[].obs; // Inside Map View Controller

Then, in Google map widget replace marker property

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());
            },
          ))

And in the getMarkers function

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
    });
  }
}
Related