maplibre / flutter-maplibre-gl

Customizable, performant and vendor-free vector and raster maps, flutter wrapper for maplibre-native and maplibre-gl-js (fork of flutter-mapbox-gl/maps)
https://pub.dev/packages/maplibre_gl
Other
224 stars 123 forks source link

[BUG] Stacking Flutter Widgets on top of MaplibreMap results in Memory Problems #489

Closed Heidi0039 closed 2 months ago

Heidi0039 commented 2 months ago

Platforms

iOS

Version of flutter maplibre_gl

Bug Description

When using MaplibreMap in a Stack that contains many other Elements as well as a Button, a tap on the Button results in the devices memory blowing out of proportion.

This can be observed using the xCode Memory profiler.

I am unsure if this is a problem with Maplibre specifically or a more general problem with native views in flutter. However, I could not recreate this using my own implementation of some other platform views (which hosted native ad containers).

The same code on android is working with no noticable problems. It seems like the memory is rising on android as well, but unlike iOS, it is promptly released on android.

I tried to reduce this problem to its simplest case. The 10000 Text elements are a simple representation of other more complex widgets. In a real app we would have other widgets resulting in this problem (e.g. a DetailPage of a POI).

Steps to Reproduce

  1. Use flutter-maplibre-gl example "FullPageMap".
  2. Replace the build method in full_map.dart with the reproducable code.
  3. Run the App an navigate to the Full Page example.
  4. Tap the Button repeatedly.

Expected Results

Tapping the Button does not affect the devices memory, as the button itself has no logic in its onPressed.

Actual Results

Tapping the Button increases the apps memory usage indefinitely until it is killed by the os.

Screenshot 2024-08-22 at 16 09 09

Code Sample

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: [
          MapLibreMap(
            onMapCreated: _onMapCreated,
            initialCameraPosition: const CameraPosition(target: LatLng(0.0, 0.0)),
            onStyleLoadedCallback: _onStyleLoadedCallback,
          ),
          Stack(
            children: List<Widget>.generate(10000, (index) {
              return Text("Having these Text widgets on top of the map is expensive.");
            }),
          ),
          CupertinoButton(
            child: Text("Button"),
            color: CupertinoColors.systemBlue,
            onPressed: () {
              print("Tap ${DateTime.now()}");
            },
          ),
        ],
      ),
    );
  }

Note

When removing either the MapLibreMap or the Stack with 10000 Texts, the Problem no longer occurs. It is only present in the combination of having many Widgets overlap the MapWidget while also having the Button. If the Button gets replaced with a GestureDetector with an onTap instead, the Problem also no longer occurs. The CupertinoButton is just one example. I have tried it using some MaterialButtons (TextButton, ...) which also result in the Problem.

Heidi0039 commented 2 months ago

Are there any news on this topic? I imagine its quit tricky to locate and understand whats actually happening.

I am not sure if this can be worked in the framework or if its an underlying flutter issue, but I would appreciate some thoughts or info on where we are at. I'm wondering if I should start looking for a workaround or other fixes, but as of now the exploding memory usage makes this unusable in our app.

josxha commented 2 months ago

Hi @Heidi0039, flutter-maplibre-gl currently relies on community contributions. Feel free to open a pull request for a bug fix or performance improvements.

I have currently no iOS testing setup so it won't be possible to do any investigation myself. Although, some thoughts of where to look into are:

Feel free to post any update, so others can help. (:

Heidi0039 commented 2 months ago

Hi @josxha, thanks for your reply and giving me some directions.

I have looked into this a bit more by now. It turns out the problem is already present using other native views. In my app it just happens to be the MaplibreMap that causes it. I could now reproduce the same behaviour using a clean UiKitView instead.

As far as flutter-maplibre-gl is concerned the issue can be closed.