lambduh
lambduh

Reputation: 43

How to use geocode to display the current address of the center of the google map in Flutter?

I am trying to project on screen the address of the center of the google map in Flutter with the help of GeoCode but I am having problem dealing with Futures. Here is my code:

  class _ManageLocationPage extends State<ManageLocationPage> {
  final List<Marker> _markers = [];
  late GeoPoint chosenLocation;

  late final Future<Address> _getAddressFuture;

  Future<Address> getAddress(GeoPoint currentLocation) async {
    GeoCode geoCode = GeoCode();

    return await geoCode.reverseGeocoding(latitude: currentLocation.latitude, longitude: currentLocation.longitude);
  }

  @override
  void initState(){
    super.initState();
    chosenLocation = widget.startSpot;
    _getAddressFuture = getAddress(chosenLocation);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: _getAddressFuture,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            // future is completed with data, you can build
            Address addr = snapshot.data as Address;
            return Stack(
              alignment: Alignment.center,
              children: [
                GoogleMap(
                    initialCameraPosition: CameraPosition(
                        target: LatLng(
                            widget.startSpot.latitude, widget.startSpot.longitude),
                        zoom: 18),
                    zoomControlsEnabled: false,
                    compassEnabled: false,
                    indoorViewEnabled: true,
                    mapToolbarEnabled: false,
                    onMapCreated: (controller) {
                      final marker = Marker(
                        markerId: MarkerId('0'),
                        position: LatLng(
                            widget.startSpot.latitude, widget.startSpot.longitude),
                      );
                      _markers.add(marker);
                    },
                    onCameraMove: (position) {
                      chosenLocation = GeoPoint(position.target.latitude, position.target.longitude);
                      setState(() {
                        _markers.first =
                            _markers.first.copyWith(positionParam: position.target);
                      });
                    },

                ),
                Positioned(
                  top: Dimensions.height45 + Dimensions.height10,
                  left: Dimensions.width20,
                  right: Dimensions.width20,
                  child: Container(
                      padding: EdgeInsets.symmetric(horizontal: Dimensions.width10),
                      height: 50,
                      decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(Dimensions.radius20/2),
                          boxShadow: [
                            BoxShadow(
                                blurRadius: 10,
                                spreadRadius: 7,
                                offset: Offset(1, 10),
                                color: Colors.grey.withOpacity(0.2)
                            )
                          ]
                      ),
                      child: Row(
                        children: [
                          Icon(Icons.storefront, size: 25, color: AppColors.iconColor1),
                          SizedBox(width: Dimensions.width10,),
                          Expanded(child: SmallText(text: addr.streetAddress.toString(),)),
                        ],
                      )
                  ),
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Padding(
                      padding: const EdgeInsets.only(bottom: 42),
                      child: Icon(
                        Icons.location_on,
                        color: AppColors.mainColor,
                        size: 50,
                      ),
                    ),
                  ],
                ),
              ],
            );
          } else if (snapshot.hasError) {
            // handler errors
            return const Text('Error');
          }
          else {
            // future is not completed yet, display a progress indicator
            return const Center(child: CircularProgressIndicator());
          }
        });
  }
}

When I try to run, I get the error type Future<Address> is not a subtype of type Address. When I don't use geocode and just display the latitude and longitude via printing chosenLocation, everything is fine and going well.

Upvotes: 0

Views: 121

Answers (1)

Peter Koltai
Peter Koltai

Reputation: 9744

In the FutureBuilder you need to check the status of the future (whether it is completed) before you build the GoogleMap. Currently, most of the times you try to build before the future completes.

Also, it is advised to store the future function in a member and not directly call it in the build method, so that it is not called multiple times.

Try the following:

class _ManageLocationPage extends State<ManageLocationPage> {
  final List<Marker> _markers = [];
  late GeoPoint chosenLocation;
  
  late final Future<Address> _getAddressFuture;
  

  Future<Address> getAddress(GeoPoint currentLocation) async {
    GeoCode geoCode = GeoCode();

    return await geoCode.reverseGeocoding(latitude: 
      currentLocation.latitude, 
      longitude: currentLocation.longitude);
  }


  @override
  void initState(){
    super.initState();
    chosenLocation = widget.startSpot;
    _getAddressFuture = getAddress(chosenLocation);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _getAddressFuture,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          // future is completed with data, you can build
          return Stack(...);
        } else if (snapshot.hasError) {
          // handler errors
          return const Text('Error');
        }
        else {
          // future is not completed yet, display a progress indicator
          return const Center(child: CircularProgressIndicator());
        }
      });
  }

Upvotes: 0

Related Questions