Пропадают кластеры и маркеры на карте Yandex mapKit Compose
Реализовал карту yandex mapKit у меня возникла проблема. У меня при зуме или при перемещении карты ИНОГДА пропадают кластеры на карте, в логах ошибка
Java object is already finalized. Nothing to do.
Я читал доку и ответы, говорят что все листенеры нужно сохранять, что бы их не очистил GC, что я и сделал. Вынес так же сами маркеры и кластеры отдельно. Но опять же, все равно пропадают иногда отметки на карте
val context = LocalContext.current
val mapView = remember { MapView(context) }
val map = remember { mapView.mapWindow.map }
val mapObjects = remember { map.mapObjects }
val clusterizedCollection = remember { mutableStateOf<ClusterizedPlacemarkCollection?>(null) }
val placemarks = remember { mutableStateOf<List<PlacemarkMapObject>>(emptyList()) }
var selectedActivity by remember { mutableStateOf<ActivityModel?>(null) }
var isFirstLocationFind by remember { mutableStateOf(false) }
var userLocationPlacemark by remember { mutableStateOf<PlacemarkMapObject?>(null) }
val imageProvider = remember {
ImageProvider.fromBitmap(
Bitmap.createScaledBitmap(
BitmapFactory.decodeResource(
context.resources,
R.drawable.ic_map_point
), 80, 100, true
)
)
}
val placemarkTapListener = remember {
MapObjectTapListener { mapObject, _ ->
val activity = mapObject.userData as? ActivityModel
selectedActivity = activity
true
}
}
val cameraListener = remember {
CameraListener { map, _, _, finished ->
if (finished) {
val visibleRegion = map.visibleRegion
loadActivities(visibleRegion)
}
}
}
val clusterTapListener = remember {
ClusterTapListener { cluster ->
if (cluster.placemarks.isNotEmpty()) {
val points = cluster.placemarks.map { it.geometry }
val minLat = points.minOf { it.latitude }
val maxLat = points.maxOf { it.latitude }
val minLon = points.minOf { it.longitude }
val maxLon = points.maxOf { it.longitude }
val centerLat = (minLat + maxLat) / 2
val centerLon = (minLon + maxLon) / 2
val centerPoint = Point(centerLat, centerLon)
map.move(
CameraPosition(
centerPoint,
map.cameraPosition.zoom + 1,
0.0f,
0.0f
),
Animation(Animation.Type.SMOOTH, 0.5f),
null
)
}
true
}
}
LaunchedEffect(state.filteredActivities) {
Log.d("ANUS", "${state.filteredActivities}")
placemarks.value.forEach {
clusterizedCollection.value?.remove(it)
}
clusterizedCollection.value?.let {
mapObjects.remove(it)
}
clusterizedCollection.value = mapObjects.addClusterizedPlacemarkCollection { cluster ->
val clusterSize = cluster.placemarks.size
val clusterIcon = createClusterIcon(context, clusterSize)
cluster.appearance.setIcon(clusterIcon)
cluster.addClusterTapListener(clusterTapListener)
}
placemarks.value = state.filteredActivities.mapNotNull { activity ->
clusterizedCollection.value?.addPlacemark()?.apply {
geometry = Point(activity.latitude, activity.longitude)
userData = activity
setIcon(imageProvider)
addTapListener(placemarkTapListener)
}
}
clusterizedCollection.value?.clusterPlacemarks(60.0, 15)
}
DisposableEffect(Unit) {
startLocation()
MapKitFactory.getInstance().onStart()
mapView.onStart()
map.addCameraListener(cameraListener)
Log.d("MAP_DEBUG", "onStart")
onDispose {
map.removeCameraListener(cameraListener)
stopLocation()
mapView.onStop()
MapKitFactory.getInstance().onStop()
Log.d("MAP_DEBUG", "onStop")
}
}
AndroidView(
factory = {
mapView.apply {
map.move(
CameraPosition(Point(59.9343, 30.3351), 10f, 0f, 0f),
Animation(Animation.Type.SMOOTH, 1f),
null
)
}
},
update = { _ ->
state.location?.let {
if (userLocationPlacemark == null) {
userLocationPlacemark = map.mapObjects.addPlacemark().apply {
geometry = it
setIcon(ImageProvider.fromResource(context, R.drawable.ic_my_location))
}
} else {
userLocationPlacemark?.geometry = it
}
if (!isFirstLocationFind) {
isFirstLocationFind = true
map.move(
CameraPosition(
it,
10f,
0f,
0f
),
Animation(Animation.Type.SMOOTH, 1f),
null
)
}
}
},
modifier = Modifier.fillMaxSize()
)
MapControls(
onZoomIn = {
val currentPosition = map.cameraPosition
map.move(
CameraPosition(
map.cameraPosition.target,
map.cameraPosition.zoom + 1,
currentPosition.azimuth,
currentPosition.tilt
),
Animation(Animation.Type.SMOOTH, 1f),
null
)
},
onZoomOut = {
val currentPosition = map.cameraPosition
map.move(
CameraPosition(
currentPosition.target,
currentPosition.zoom - 1,
currentPosition.azimuth,
currentPosition.tilt
),
Animation(Animation.Type.SMOOTH, 1f),
null
)
},
onLocationClick = {
val currentPosition = map.cameraPosition
userLocationPlacemark?.let {
map.move(
CameraPosition(
Point(it.geometry.latitude, it.geometry.longitude),
currentPosition.zoom,
currentPosition.azimuth,
currentPosition.tilt
),
Animation(Animation.Type.SMOOTH, 1f),
null
)
}
}
)
if (selectedActivity != null) {
selectedActivity?.let {
ModalBottomSheet(
sheetState = rememberModalBottomSheetState(),
onDismissRequest = {
selectedActivity = null
}
) {
Column(Modifier.padding(10.dp)) {
ActivityWithDescriptionItem(
modifier = Modifier.fillMaxWidth(),
activity = it
)
CustomRoundButton(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp),
text = "К событию"
) {
navigateToActivityDetail(it.id)
}
}
}
}
}
PS. Я вызываю насильно сборщика мусора в конце обновления кластеров, теперь кластеры просто не появляются, что говорит о том, что суть точно в GC, а плейсмарки кстати отображаются нормально
LaunchedEffect(state.filteredActivities) {
Log.d("ANUS", "${state.filteredActivities}")
placemarks.value.forEach {
clusterizedCollection.value?.remove(it)
}
clusterizedCollection.value?.let {
mapObjects.remove(it)
}
clusterizedCollection.value = mapObjects.addClusterizedPlacemarkCollection { cluster ->
val clusterSize = cluster.placemarks.size
val clusterIcon = createClusterIcon(context, clusterSize)
cluster.appearance.setIcon(clusterIcon)
cluster.addClusterTapListener(clusterTapListener)
}
placemarks.value = state.filteredActivities.mapNotNull { activity ->
clusterizedCollection.value?.addPlacemark()?.apply {
geometry = Point(activity.latitude, activity.longitude)
userData = activity
setIcon(imageProvider)
addTapListener(placemarkTapListener)
}
}
clusterizedCollection.value?.clusterPlacemarks(60.0, 15)
System.gc()
System.runFinalization()
}