marchdev-tk / flutter_google_maps

A Flutter plugin for integrating Google Maps in iOS, Android and Web applications. It is a wrapper of google_maps_flutter for Mobile and google_maps for Web.
BSD 3-Clause "New" or "Revised" License
87 stars 57 forks source link

Error received after tap over any map area other than a marker #40

Closed hackerunet closed 4 years ago

hackerunet commented 4 years ago

Environment: Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, v1.17.2, on Linux, locale es_CO.UTF-8) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [✓] Android Studio (version 3.5) [✓] IntelliJ IDEA Community Edition (version 2019.3) [!] VS Code (version 1.41.1) ✗ Flutter extension not installed; install from https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter [✓] Connected device (1 available)

Dart VM version: 2.7.0 (Unknown timestamp) on "linux_x64"

Steps to Reproduce

1) Add a marker 2) Tap over the marker to display the information window. 3) Tap over any other area over the map

Expected results: No errors should be displayed after tap in a map area without markers or any other

Actual results:

W/perpesos.mobil(20772): Accessing hidden method Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V (greylist, linking, allowed)
E/flutter (20772): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'call' was called on null.
E/flutter (20772): Receiver: null
E/flutter (20772): Tried calling: call()
E/flutter (20772): #0      GoogleMapState.build.<anonymous closure>.<anonymous closure> (package:flutter_google_maps/src/mobile/google_map.state.dart:437:46)
E/flutter (20772): #1      _GoogleMapState.onTap (package:google_maps_flutter/src/google_map.dart:352:19)
E/flutter (20772): #2      GoogleMapController._connectStreams.<anonymous closure> (package:google_maps_flutter/src/controller.dart:90:52)
E/flutter (20772): #3      _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter (20772): #4      _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (20772): #5      _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
E/flutter (20772): #6      CastStreamSubscription._onData (dart:_internal/async_cast.dart:83:11)
E/flutter (20772): #7      _rootRunUnary (dart:async/zone.dart:1192:38)
E/flutter (20772): #8      _CustomZone.runUnary (dart:async/zone.dart:1085:19)
E/flutter (20772): #9      _CustomZone.runUnaryGuarded (dart:async/zone.dart:987:7)
E/flutter (20772): #10     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)

My widget code:

import 'dart:core';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:geolocator/geolocator.dart';
import 'package:flutter_google_maps/flutter_google_maps.dart';
import 'package:spmobile/src/bloc/map/map.dart';
import 'package:spmobile/src/constants/navigation.dart';
import 'package:spmobile/src/core_services/constants_provider.dart';
import 'package:spmobile/src/models/Commerce.dart';

class MapWidget extends StatefulWidget {
  @override
  _MapWidgetState createState() => _MapWidgetState();
}

class _MapWidgetState extends State<MapWidget> {

  Position position;
  final _key = GlobalKey<GoogleMapStateBase>();

  String _mapStyle;

  _setCurrentPosition() async {
    position = await _getCurrentPosition();
  }

  GeoCoordBounds boundsFromLatLngList(List<GeoCoord> list) {
    assert(list.isNotEmpty);
    double x0, x1, y0, y1;
    for (GeoCoord latLng in list) {
      if (x0 == null) {
        x0 = x1 = latLng.latitude;
        y0 = y1 = latLng.longitude;
      } else {
        if (latLng.latitude > x1) x1 = latLng.latitude;
        if (latLng.latitude < x0) x0 = latLng.latitude;
        if (latLng.longitude > y1) y1 = latLng.longitude;
        if (latLng.longitude < y0) y0 = latLng.longitude;
      }
    }
    return GeoCoordBounds(northeast: GeoCoord(x1, y1), southwest: GeoCoord(x0, y0));
  }

  Future<Position> _getCurrentPosition() async {
    Position position = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    if (position != null) {
      return position;
    }
  }

  @override
  void initState() {
    GoogleMap.init(ConstantsProvider.GOOGLE_API_KEY);
    WidgetsFlutterBinding.ensureInitialized();
    _setCurrentPosition();
  }

  @override
  Widget build(BuildContext context) {
    final MapBloc _mapBloc = BlocProvider.of<MapBloc>(context);

    return BlocListener(
      bloc: _mapBloc,
      listener: (context, state){
      },
      child: BlocBuilder(
        bloc: _mapBloc,
        builder: (context, state) {
          if(state is ShowCompaniesInMapState) {
            if(GoogleMap.of(_key) != null) {
              GoogleMap.of(_key).clearMarkers();
              List<GeoCoord> _positions = [];
              /// Add current location coordinates
              if (position != null) {
                _positions.add(GeoCoord(position.latitude, position.longitude));
              }
              state.records.forEach((Commerce element) {
              if (element != null) {
                _positions.add(GeoCoord(element.location[1], element.location[0]));
                GoogleMap.of(_key).addMarkerRaw(
                  GeoCoord(element.location[1], element.location[0]),
                  icon: 'assets/images/icons/sp_pin.png',
                  info: '${element.commerceName}',
                  infoSnippet: """Direccion: ${element.address}""",
                  label: ' NIT: ${element.nit}',
                  onInfoWindowTap: () async {
                    Navigator.of(context).pushNamed(companyDetail);
                  },
                );
              }
            });
            GoogleMap.of(_key).moveCamera(
                boundsFromLatLngList(_positions), padding: 100, animated: false
            );
          }
        }
          return Center(
            child: Container(
              child: GoogleMap(
                key: _key,
                initialZoom: 14,
                initialPosition: GeoCoord(4.707756, -74.073209),
                mapType: MapType.roadmap,
                mapStyle: _mapStyle,
                interactive: true,
                mobilePreferences: const MobileMapPreferences(
                  trafficEnabled: false,
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}
randomdude583 commented 4 years ago

Is this on Flutter Web, Android or iOS? I think that this code base fails to check if there is an onTap callback, so it tries to call on null. It should be straightforward to fix, but an easy workaround is to just pass an empty onTap to the GoogleMap object like this: onTap: (LatLng pos){}

march-dev commented 4 years ago

Done in 3.8.0