Mikelenjilo
Mikelenjilo

Reputation: 505

How to display markers using GetX?

So, I have a Flutter app that's using mainly these packages: flutter_map, get, LatLng2. I'm using GetX as a state management and my goal is to get data from a rest api, and display this data into the screen. Here is my setup.

First I have this MapController:

class MapAppController extends GetxController {
  LatLng center = LatLng(28.0339, 1.6596);
  Marker? userLocationMarker;
  bool isLoading = false;
  List<Marker> markers = [];

  Future<void> getLocation() async {
    isLoading = true;
    update();

    LocationPermission permission = await Geolocator.requestPermission();

    if (permission == LocationPermission.denied) {
      // TODO: handle the scenario when the user denies location permission
    } else if (permission == LocationPermission.deniedForever) {
      // TODO: handle the scenario when the user denies location permission permanently
    } else {
      Position position = await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high);

      LatLng userLocation = LatLng(position.latitude, position.longitude);
      center = userLocation;
      userLocationMarker = Marker(
        width: 40.0,
        height: 40.0,
        point: userLocation,
        builder: (ctx) => const Icon(
          Icons.location_on,
          size: 45,
          color: Colors.red,
        ),
      );

      isLoading = false;
      update();
    }
  }

  Future<void> populateMarkers() async {
    isLoading = true;
    update();

    final Map<String, LatLng> clustersCentroid =
        await DjangoHelper.getClusterCentroid();

    markers.clear();

    for (var cluster in clustersCentroid.entries) {
      markers.add(
        Marker(
          width: 80.0,
          height: 80.0,
          point: cluster.value,
          builder: (ctx) => const Icon(
            Icons.circle,
            size: 70,
            color: Colors.green,
          ),
        ),
      );
    }

    isLoading = false;
    update();
  }
}

This controller mainly has two methods: getLocation() which gets the user's location, create a Marker from the flutter_map package and display his position using an icon form the Flutter library, this method is working perfctly, I'm successfly displaying the user's location.

The second method get's the centroid positions (Cluster centroids generated using the k-means algorithm) it clears the markers (In case there was markers before), and then for each cluster it creates a marker and add it to the markers list, finally it rebuilds the GetBuilder() which are listening to the MapController controller, I guess that's what must be done, but it's not displaying those clusters. The user location is displaying perfectly, but I'm having issues with the clustesr centroids markers.

Here is the map page where I'm calling these methods:

final mapController = Get.find<MapAppController>();
final userInfoController = Get.find<InscriptionController>();

class MapPage extends StatelessWidget {
  const MapPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GetBuilder<MapAppController>(
        builder: (controller) => Stack(
          children: [
            FlutterMap(
              options: MapOptions(
                center: controller.center,
                zoom: 5.0,
              ),
              children: [
                TileLayer(
                  urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
                  subdomains: const ['a', 'b', 'c'],
                ),
                MarkerLayer(
                  markers: [
                    if (mapController.userLocationMarker != null)
                      mapController.userLocationMarker!,
                    if (mapController.markers.isNotEmpty)
                      ...mapController.markers,
                  ],
                ),
              ],
            ),
            Visibility(
              visible: mapController.isLoading,
              child: const CustomLoadingIndicator(),
            ),
            FloatingActionButton(
              onPressed: () async {
                await mapController.populateMarkers();
              },
              child: const Icon(Icons.info),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await mapController.getLocation();
        },
        child: const Icon(Icons.gps_fixed),
      ),
    );
  }
}

Upvotes: 0

Views: 730

Answers (1)

Jawad Abbasi
Jawad Abbasi

Reputation: 146

Make markers list as an obs list like this:

RxList<Marker> markers = <Marker>[].obs;

Use it in the view like this :

MarkerLayer(
    markers: [
      if (mapController.markers.value.isNotEmpty)
        {
          mapController.markers,
        }
    ],
  )

Upvotes: 0

Related Questions