4

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

WatsMyName
  • 4,240
  • 5
  • 42
  • 73

1 Answers1

6

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
    });
  }
}
Faiz Shahid
  • 297
  • 3
  • 9
  • 1
    Thanks for the reply! won't `Obx( () -> GoogleMap (...` refreshes/reloads Googlemap everytime new marker data comes? – WatsMyName Dec 28 '21 at 02:58
  • Also what if i move `getMarkers()` method on controller itself? – WatsMyName Dec 28 '21 at 03:06
  • @WatsMyName Actually you don't need to wrap Google map widget inside Obx because Google map already wrap in Get builder so using Obx at this stage is unnecessary and yeah whenever change received by builder it will re render it's child – Faiz Shahid Dec 28 '21 at 04:07
  • @WatsMyName And moving getMarkers inside controller is a recommend way. If you have controller for specific screen then you should write all the functionalities related to the screen inside controller – Faiz Shahid Dec 28 '21 at 04:09
  • Isn't there a way to prevent re-rendering of google map? The changes occurs only in Marker's position, so it is not a good idea to re-render whole map. And google charges amount for every time map is reloaded i think. – WatsMyName Dec 28 '21 at 04:13
  • I don't think there is a way to prevent re-rendering because Getx reconstruct child if change occur actually. You can read more here: [state management](https://github.com/jonataslaw/getx/blob/master/documentation/en_US/state_management.md#state-management) – Faiz Shahid Dec 28 '21 at 04:33
  • @WatsMyName There aren't any charges for loading map in application. You can check more: [usage and billing](https://developers.google.com/maps/documentation/android-sdk/usage-and-billing#mobile-dynamic) – Faiz Shahid Dec 28 '21 at 04:37