Flutter Google Map Markers are shown only after hot reload - using with cubit and custom marker

452 Views Asked by At

I'm struggling second day on this issue.

I use flutter google map to show about hundred custom markers with network image icons, that can be svg or png (using MarkerGenerator).

After opening the map page, MapCubit start to load items from API. In build i have BlocConsumer, where is listener, that build markers when loaded in that cubit and builder that build GoogleMap.

Problem is, that on first opening of page there are no images in markers, only white circle. When I tried to set one image url to all markers, it was loaded properly. Then, when i go on previous page or hot reload (not always), icons are there. On same page i have legend, that draw images from same urls, where images are set properly in most times. Sometimes it is need to go back and forward more times.

I can load icons after click on item in filter, that calls MapCubit, too.

I dont know, if it means something, but next problem, what i have is, that on release and appbundle build, no map is shown, only grey screen, buttons on side and google logo on bottom left.

I tried many tips on internet, but nothing helped.

Preview of first opening of MapPage

Preview of filter at first opening (has all icons)

Preview of second opening of MapPage

Preview of third opening of MapPage (has all icons)

MapPage (MarkerGenerator is in listener and initState becouse of two different uses that needs it)

class _MapAreaState extends State<MapArea> {
  MapCubit _mapCubit;
  Set<Marker> markers = {};
  List<CustomMarker> markerWidgets = [];
  bool markersLoaded = false;

  @override
  void initState() {
    _mapCubit = BlocProvider.of<MapCubit>(context);
    markers = {};

    MarkerGenerator(
        _mapCubit.state.items.map((e) => CustomMarker(type: e.type)).toList(),
        (bitmaps) {
      setState(() {
        bitmaps.asMap().forEach((mid, bmp) {
          IMapItem item = _mapCubit.state.items[mid];
          markers.add(Marker(
              markerId: MarkerId(item.title),
              position: item.latLng,
              icon: BitmapDescriptor.fromBytes(bmp),
              // markerId: MarkerId(item.title),
              // position: item.latLng,
              onTap: () async {
                await _mapCubit.showDetail(item);
              }));
        });
      });
    }).generate(context);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: tercialBackgroundColor,
      child: BlocConsumer<MapCubit, MapState>(
        bloc: _mapCubit,
        listener: (context, state) {

          if (state.changedItems && state.items.isNotEmpty) {
            markerWidgets = _mapCubit.state.items
                .map((e) => CustomMarker(type: e.type))
                .toList();

            markers = {};
            MarkerGenerator(markerWidgets, (bitmaps) {
              setState(() {
                bitmaps.asMap().forEach((mid, bmp) {
                  log(bmp.toString());

                  IMapItem item = _mapCubit.state.items[mid];
                  markers.add(Marker(
                      markerId: MarkerId(item.title),
                      position: item.latLng,
                      icon: BitmapDescriptor.fromBytes(bmp),
                      // markerId: MarkerId(item.title),
                      // position: item.latLng,
                      onTap: () async {
                        await _mapCubit.showDetail(item);
                      }));
                });
              });
            }).generate(context);
          }
        },
        builder: (context, state) {
          return Stack(
            children: [
              GoogleMap(
                zoomControlsEnabled: false,
                compassEnabled: false,
                markers: markers,
                // markers: Set<Marker>.of(state.markers),
                initialCameraPosition: CameraPosition(
                  target: state.items.length == 1
                      ? state.items[0].latLng
                      : LatLng(49.07389317899512, 19.30980263713778),
                  zoom: 8.5,
                ),
                minMaxZoomPreference: MinMaxZoomPreference(8, 22),
                cameraTargetBounds: CameraTargetBounds(LatLngBounds(
                  northeast: LatLng(50.16477808289659, 20.56397637952818),
                  southwest: LatLng(48.75267922516721, 18.76330228064009),
                )),
                onMapCreated: (GoogleMapController controller) {
                  if (!_mapCubit.controller.isCompleted) {
                    rootBundle
                        .loadString('assets/googleMapsStyle.json')
                        .then((string) async {
                      controller.setMapStyle(string);
                    });

                    _mapCubit.controller.complete(controller);
                    log(_mapCubit.controller.toString());
                    log(controller.toString());
                    setState(() {

                    });
                  }
                },
              ),

              // if(state.items.isEmpty)
              // FullScreenLoadingSpinner()
            ],
          );
        },
      ),
    );
  }
}

CustomMarker class

class CustomMarker extends StatelessWidget {
  final ItemType type;

  const CustomMarker({Key key, this.type}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // precachePicture(
    //   svgPicture.pictureProvider,
    //   Get.context!,
    // );

    // if(type.icon is /-

    return  Stack(
      clipBehavior: Clip.none,
      children: [
        Icon(
          Icons.add_location,
          color: type.color,
          size: 56,
        ),
        Positioned(
          left: 16,
          top: 10,
          child: Container(
            width: 24,
            height: 24,
            decoration: BoxDecoration(
                color: primaryBackgroundColor,
                borderRadius: BorderRadius.circular(10)),
            child: Padding(
              padding: const EdgeInsets.all(1.0),
              child: Center(child: type.icon),
            ),
          ),
        ),
      ],
    );
  }
}

Icon setting in ItemType factory, that is used in CustomMarker

icon: map['icon'] != null
            ? (map['icon'] is Image
                ? map['icon']
                : (map['icon'].substring(map['icon'].length - 4) == '.svg'
                    ? WebsafeSvg.network(
                        map['icon'],
                        width: 18,
                        height: 18,
                        color: Colors.black,
                        placeholderBuilder: (BuildContext context) => Container(
                            padding: const EdgeInsets.all(30.0),
                            child: const CircularProgressIndicator()),
                      )
                    : Image.network(map['icon'])))

Lately somewhen this exception is in console

======== Exception caught by image resource service =====================
The following HttpException was thrown resolving an image codec:
, uri = https://www.xxx.sk/images/svgs/culture.png

When the exception was thrown, this was the stack: 
Image provider: NetworkImage("https://www.xxx.sk/images/svgs/culture.png", scale: 1.0)
Image key: NetworkImage("https://www.xxx.sk/images/svgs/culture.png", scale: 1.0)

I dont know, what all to send, so far at least this. Thanks.

0

There are 0 best solutions below