mapbox / mapbox-maps-flutter

Interactive, thoroughly customizable maps for Flutter powered by Mapbox Maps SDK
https://www.mapbox.com/mobile-maps-sdk
Other
294 stars 120 forks source link

App freeze with multiple ImageSource and flickering #764

Open jonancastelo opened 1 week ago

jonancastelo commented 1 week ago

Hello,

Problems:

I have an app that loads 100 ImageSource in a map using a for loop:

Future<void> _addMapLayers() async {
    if (satData != null) {
      for (int i = 0; i < satData!.length; i++) {
        final id = 'sat-$i';
        await _addMapLayer(id, satData![i]);
      }
    }
  }

Future<void> _addMapLayer(String id, SatDataItem satDataItem) async {
    final styleSource = {
      "url": satDataItem.url,
      "coordinates": [
        [x, y,
        [f, d],
        [t, a],
        [u, i],
      ],
      "type": 'image',
    };
    final styleLayer = {
      "id": id,
      "source": id,
      "type": 'raster',
      "paint": {
        'raster-opacity': 0.8,
        'raster-fade-duration': 0,
        'raster-opacity-transition': {"delay": 0, "duration": 0},
      },
      "layout": {
        "visibility": 'none',
      },
    };
    await _mapboxMap!.style.addStyleSource(
      id,
      json.encode(styleSource),
    );
    await _mapboxMap!.style.addStyleLayer(
      json.encode(styleLayer),
      null,
    );
  }

Each image has a size of 80,5 KB aproximatelly.

When using the url property to load them, the app freezes when the loop index is equal to 62, and to reach the 62 position, it requires more time that to reach the position 2; the time to add each new image increments exponentially.

If I don't use the url property and try to add the same images from my assets (as a probe of concept) it loads them without freezing the app. So it could be related to each image fetching:

 Future<void> _setMapSourcesImage() async {
    for (int i = 0; i < satData!.length; i++) {
      final id = 'sat-$i';
      mapbox.ImageSource? currentSource;

      try {
        currentSource =
            await mapboxMap?.style.getSource(id) as mapbox.ImageSource?;
      } catch (e) {
        log('_setMapSourcesImage error', error: e);
      }

      if (currentSource != null) {
        await _setMapSourceImage(
          currentSource,
          satData![i],
          i,
        );
      }
    }
  }

  Future<void> _setMapSourceImage(
    mapbox.ImageSource? currentSource,
    SatDataItem satDataItem,
    int i,
  ) async {
    if (currentSource != null) {
      try {
        // Load the image bytes from assets
        final ByteData bytes =
            await rootBundle.load('assets/images/demo_1 copy $i.webp');
        final Uint8List list = bytes.buffer.asUint8List();

        // Decode the image to get its dimensions
        ui.Image image = await decodeImageFromList(list);
        int width = image.width;
        int height = image.height;

        await currentSource.updateImage(
          mapbox.MbxImage(
            width: width,
            height: height,
            data: list,
          ),
        );
      } catch (e) {
        log('_setMapSourceImage error', error: e);
      }
    }
  }

Although images are loaded from assets, and the app no freezes, when changing the visibility of them, there is a flickering that is not allowing a smooth transition of images without seeing the background:

 Future<void> _updateMapLayersVisibility() async {
    if (satData != null && _sliderValues != null) {
      DateTime sliderCurrentValue = DateTime.fromMillisecondsSinceEpoch(
        (_sliderValues!.currentValue * 1000).toInt(),
      );
      for (int i = 0; i < satData!.length; i++) {
        final id = 'sat-$i';

        final isCurrentSatDataItem = satData![i].dtg.isAtSameMomentAs(
              sliderCurrentValue,
            );

        if (isCurrentSatDataItem) {
          await mapboxMap!.style.setStyleLayerProperty(
            id,
            'visibility',
            'visible',
          );
        } else {
          await mapboxMap!.style.setStyleLayerProperty(
            id,
            'visibility',
            'none',
          );
        }
      }
    }
  }

Non of this problems exist in mapbox gl js. I am using the same code (adapted to js).

Thx.

evil159 commented 1 week ago

Hi @jonancastelo, thank you for your report, could you please attach a minimal sample project showcasing this issue?