@maydon_tech/react-native-nitro-maps 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,6 +58,9 @@ class HybridNitroMap(context: Context) : HybridNitroMapSpec() {
58
58
  private var isDisposed = false
59
59
 
60
60
  init {
61
+ // Tag container so the ViewManager can retrieve this instance for proper disposal
62
+ container.setTag(R.id.nitro_map_hybrid_view, this)
63
+
61
64
  container.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
62
65
  override fun onViewAttachedToWindow(v: View) {
63
66
  if (!isDisposed) {
@@ -72,8 +75,14 @@ class HybridNitroMap(context: Context) : HybridNitroMapSpec() {
72
75
  }
73
76
 
74
77
  private fun attachMapView() {
75
- if (currentMapView != null) return // already attached
78
+ if (currentMapView != null) {
79
+ // Reattaching — reuse existing MapView, just resume it
80
+ mapProvider.onViewAttached(currentMapView!!)
81
+ Log.d(TAG, "MapView reattached (resumed)")
82
+ return
83
+ }
76
84
 
85
+ // First time — create and add to container
77
86
  val mv = mapProvider.createMapView(mapContext)
78
87
  container.addView(mv, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
79
88
 
@@ -81,16 +90,15 @@ class HybridNitroMap(context: Context) : HybridNitroMapSpec() {
81
90
  mapProvider.onViewAttached(mv)
82
91
  }
83
92
  currentMapView = mv
84
- Log.d(TAG, "MapView attached")
93
+ Log.d(TAG, "MapView created and attached")
85
94
  }
86
95
 
87
96
  private fun detachMapView() {
88
- currentMapView?.let { mv ->
89
- mapProvider.onViewDetaching()
90
- container.removeView(mv)
91
- }
92
- currentMapView = null
93
- Log.d(TAG, "MapView detached (paused, state saved)")
97
+ if (currentMapView == null) return
98
+ mapProvider.onViewDetaching()
99
+ // Keep currentMapView and the view in the container — reuse on reattach.
100
+ // The MapView and GoogleMap survive pause/resume cycles.
101
+ Log.d(TAG, "MapView paused (preserved for reattach)")
94
102
  }
95
103
 
96
104
  override fun dispose() {
@@ -6,11 +6,12 @@ import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.module.model.ReactModuleInfoProvider
7
7
  import com.facebook.react.uimanager.ViewManager
8
8
 
9
- import com.margelo.nitro.nitromap.views.HybridNitroMapManager
10
-
11
9
  /**
12
10
  * React Native Package for NitroMap.
13
11
  * Registers the ViewManager and loads the native C++ library.
12
+ *
13
+ * Uses NitroMapViewManager (our subclass) instead of the generated
14
+ * HybridNitroMapManager to add proper MapView disposal on onDropViewInstance.
14
15
  */
15
16
  class NitroMapPackage : BaseReactPackage() {
16
17
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
@@ -22,7 +23,7 @@ class NitroMapPackage : BaseReactPackage() {
22
23
  }
23
24
 
24
25
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
25
- return listOf(HybridNitroMapManager())
26
+ return listOf(NitroMapViewManager())
26
27
  }
27
28
 
28
29
  companion object {
@@ -0,0 +1,34 @@
1
+ package com.margelo.nitro.nitromap
2
+
3
+ import android.util.Log
4
+ import android.view.View
5
+ import com.margelo.nitro.nitromap.views.HybridNitroMapManager
6
+
7
+ /**
8
+ * Custom ViewManager that extends the Nitrogen-generated HybridNitroMapManager
9
+ * to add proper MapView lifecycle management.
10
+ *
11
+ * The generated manager doesn't call dispose() on the HybridNitroMap when the
12
+ * view is dropped, which leaks the MapView (GL surface, GoogleMap instance,
13
+ * coroutine scope, etc.). This subclass retrieves the HybridNitroMap via a
14
+ * View tag set in HybridNitroMap.init and calls dispose() before the view
15
+ * is released.
16
+ */
17
+ class NitroMapViewManager : HybridNitroMapManager() {
18
+
19
+ companion object {
20
+ private const val TAG = "NitroMap"
21
+ }
22
+
23
+ override fun onDropViewInstance(view: View) {
24
+ // Retrieve the HybridNitroMap from the tag and dispose it before
25
+ // the generated manager removes it from its internal views map.
26
+ val hybridMap = view.getTag(R.id.nitro_map_hybrid_view) as? HybridNitroMap
27
+ if (hybridMap != null) {
28
+ hybridMap.dispose()
29
+ view.setTag(R.id.nitro_map_hybrid_view, null)
30
+ Log.d(TAG, "ViewManager: disposed HybridNitroMap on drop")
31
+ }
32
+ super.onDropViewInstance(view)
33
+ }
34
+ }
@@ -67,6 +67,18 @@ class GoogleMapProvider(internal val context: Context) : MapProviderInterface {
67
67
 
68
68
  override fun onViewAttached(view: View) {
69
69
  val mv = view as NitroMapView
70
+ if (isMapReady && googleMap != null) {
71
+ // Resuming from detach — GoogleMap is still valid, just resume the MapView
72
+ mv.onStart()
73
+ mv.onResume()
74
+ // Force Fabric to re-layout the GL surface. After onStop/onStart the
75
+ // GL surface may be recreated, but Yoga won't trigger requestLayout for
76
+ // an already-measured view — resulting in a blank map.
77
+ mv.post { mv.requestLayout() }
78
+ Log.d(TAG, "MapView resumed — GoogleMap still valid")
79
+ return
80
+ }
81
+ // First attach — need async init
70
82
  mv.getMapAsync { googleMap ->
71
83
  onMapReady(googleMap, mv)
72
84
  }
@@ -74,14 +86,12 @@ class GoogleMapProvider(internal val context: Context) : MapProviderInterface {
74
86
 
75
87
  override fun onViewDetaching() {
76
88
  mapView?.let { mv ->
77
- val state = Bundle()
78
- mv.onSaveInstanceState(state)
79
- savedState = state
80
89
  mv.onPause()
81
90
  mv.onStop()
82
91
  }
83
- onMapDetaching()
84
- mapView = null
92
+ // Keep mapView, googleMap, isMapReady, and all rendered objects alive.
93
+ // GoogleMap and its native markers/overlays survive pause/resume cycles.
94
+ Log.d(TAG, "MapView paused — all state preserved for reattach")
85
95
  }
86
96
 
87
97
  override fun onViewDestroying() {
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <item name="nitro_map_hybrid_view" type="id" />
4
+ </resources>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maydon_tech/react-native-nitro-maps",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "A high-performance React Native map library powered by Nitro Modules with support for Apple Maps, Google Maps, and Yandex Maps. Features native clustering, custom markers, and seamless cross-platform integration.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",