Fabric: ReactViewGroup cannot be cast to MapMarker in MarkerManager.onLayoutChange (leaked layout listener on recycled views)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 84/100
Línea de trabajo
Comienza en android/src/main/java/com/rnmaps/fabric/MarkerManager.java, en addView y su callback onLayoutChange, y luego reproduce el escenario de reciclaje de marcadores de Fabric reportado con contenido de marcador personalizado. Se considera terminado cuando los elementos secundarios reciclados ya no provocan un fallo cuando su elemento principal no es un MapMarker y el callback ya no afecta a los marcadores desconectados; verifícalo con la reproducción de Android proporcionada.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
On the New Architecture (Fabric), MarkerManager.addView attaches an OnLayoutChangeListener to a marker's first child and never removes it. Because Fabric recycles views through a shared pool, that listener stays attached to the view after it has been reparented elsewhere, and the unchecked cast in the callback crashes the app:
com.facebook.react.views.view.ReactViewGroup cannot be cast to com.rnmaps.maps.MapMarker
at com.rnmaps.maps.MarkerManager.onLayoutChange(MarkerManager.java:292)
at android.view.View.layout(View.java:27317)
at android.view.ViewGroup.layout(ViewGroup.java:6513)
at com.facebook.react.fabric.mounting.SurfaceMountingManager.updateLayout(SurfaceMountingManager.kt:856)
at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute(IntBufferBatchMountItem.kt:139)
at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems(MountItemDispatcher.kt:250)
at com.facebook.react.fabric.FabricUIManager.doFrameGuarded(FabricUIManager.java:1622)
Cause
android/src/main/java/com/rnmaps/fabric/MarkerManager.java:
if (index == 0) {
child.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, ...) {
int newWidth = right - left;
int newHeight = bottom - top;
MapMarker marker = (MapMarker) v.getParent(); // <-- unchecked
if (marker != null) {
marker.update(newWidth, newHeight);
}
}
});
}
The existing marker != null check does not help: the problem is not a null parent, it is a parent of the wrong type. The listener is registered once per addView and is never paired with a removeOnLayoutChangeListener, so it outlives the marker that installed it.
Reproduction
Using custom marker content (a <View> child rather than pinColor) for a set of markers that mount and unmount as data arrives, on a screen that also renders a reasonable number of ordinary <View>s:
<MapView>
{riders.map(r => (
<Marker key={r.uid} coordinate={{ latitude: r.lat, longitude: r.lng }}>
<View style={styles.wrap}>
<View style={styles.arrow} />
<View style={styles.pill}><Text>{r.name}</Text></View>
</View>
</Marker>
))}
</MapView>
It is a race, so it does not reproduce on every launch. It became reliably reproducible in our app once the surrounding screen grew enough plain Views for the pool to hand a recycled marker child back out.
Environment
- react-native-maps 1.29.0
- react-native 0.87.1, New Architecture / Fabric enabled
- Android,
PROVIDER_GOOGLE
Suggested fix
Guard the cast:
- MapMarker marker = (MapMarker) v.getParent();
- if(marker != null){
- marker.update(newWidth, newHeight);
+ if (v.getParent() instanceof MapMarker) {
+ ((MapMarker) v.getParent()).update(newWidth, newHeight);
}
This has been running via patch-package in our app and resolves the crash with no behavioural change.
A more complete fix would also remove the listener when the child is detached (removeViewAt / onDropViewInstance), so recycled views do not keep firing callbacks into markers that no longer exist. I am happy to open a PR for either shape if you have a preference.
- Lenguaje dominante
- TypeScript
- Estrellas
- 16k
- Forks
- 5k
- Merge medio
- 17 h 45 min
- PR fusionados (30 d)
- 2
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de react-native-maps/react-native-maps
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 88/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 90/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
react-native-maps/react-native-maps#5977 · 2 comentarios · 1 reacción ·
Todos los issues de react-native-maps/react-native-maps
Issues similares
-
blocklist removal
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
MetaMask/eth-phishing-detect#296544 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
pastelsky/bundlephobia#1122 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
-
category/development priority/P2 scope/file-operations scope/testing type/enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Enatega Customer and Rider app: Add-ons price is not visible to customer after order is placed. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100