Android Kotlin中Mapbox地图GeoJson解析并发修改异常求助
异常日志
FATAL EXCEPTION: GEOJSON_PARSER
Process: com.example.test, PID: 10995
com.mapbox.maps.MapboxConcurrentGeometryModificationException: 向id为"line"的GeoJson数据源应用FeatureCollection时,集合被修改(解析在其他线程执行,不允许此操作)。
请确保通过geometry、feature、featureCollection方法传入的所有集合均为不可变对象。最简单的实现方式是传入全新副本,或使用CopyOnWriteArrayList。
at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.toPropertyValue(GeoJsonSource.kt:337)
at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.applyGeoJsonData$lambda-11$lambda-10(GeoJsonSource.kt:353)
at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.$r8$lambda$_9l_l-ZA5tTLYApH7jbY6OB3HUI(Unknown Source:0)
at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource$$ExternalSyntheticLambda1.run(Unknown Source:4)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.os.HandlerThread.run(HandlerThread.java:67)
异常原因
Mapbox的GeoJSON解析在独立线程执行,若传入的FeatureCollection、Feature或Geometry集合在解析过程中被其他线程修改,就会触发该并发修改异常。
解决方案
- 传入集合的全新副本:每次调用
featureCollection、feature或geometry方法时,创建原集合的深拷贝,确保解析线程使用的是独立且不会被外部修改的对象。
示例代码(Kotlin):
针对列表类型集合,可直接用// 基于原FeatureCollection创建不可变副本 val immutableFeatureCollection = FeatureCollection.fromJson(originalFeatureCollection.toJson()) geoJsonSource.featureCollection(immutableFeatureCollection)toList()创建副本:val immutableFeatures = originalFeatures.toList() val featureCollection = FeatureCollection.fromFeatures(immutableFeatures) geoJsonSource.featureCollection(featureCollection) - 使用CopyOnWriteArrayList存储集合:如果需要频繁修改集合但要避免并发问题,用
CopyOnWriteArrayList替代普通ArrayList。该类在修改时会创建底层数组的新副本,保证读取操作线程安全,适配Mapbox的解析场景。
示例代码(Kotlin):val features = CopyOnWriteArrayList<Feature>() // 向集合添加/修改元素 features.add(newFeature) // 传入Mapbox的GeoJsonSource geoJsonSource.featureCollection(FeatureCollection.fromFeatures(features))
内容的提问来源于stack exchange,提问作者Kawan Osman

