У меня есть поток в компонуемом экране, постоянно получающий от серверной части новые значения, которые я преобразую в смещения экрана для целей анимации и помещаю на карту с именем маркерыMap:
@Composable
fun Screen() {
val receivedFlow = viewModel.receiverFlow.collectAsStateWithLifecycle(
initialValue = null,
minActiveState = Lifecycle.State.RESUMED
)
receivedFlow.value?.let { received ->
markersMap[received.stationId]?.offset = markersMap[received.stationId]?.nextOffset
markersMap[received.stationId]?.nextOffset = Offset(received.x, received.y)
}
}
Затем у меня есть компонуемый цикл каждую секунду по всем элементам в маркерах, чтобы создать анимацию от их предыдущего смещения до следующего смещения
@Composable
fun NativeMarkersAnimator() {
val offsetsMap = remember {
mutableStateMapOf()
}
LaunchedEffect(Unit) {
while (true) {
markersMap.forEach { marker ->
val targetOffset = marker.value.nextOffset
targetOffset?.let { target ->
offsetsMap[marker.value.stationId] =
Animatable(marker.value.offset, Offset.VectorConverter)
offsetsMap[marker.value.stationId]?.animateTo(target, tween(900))
}
}
delay(1000)
}
}
//CANVAS
}
и, очевидно, также внутриNativeMarkersAnimator, Canvas, который будет перекомпонован для рендеринга анимации:
@Composable
fun NativeMarkersAnimator() {
val offsetsMap = remember {
mutableStateMapOf()
}
// LAUNCHED EFFECT in code snippet above
Canvas(modifier = Modifier.fillMaxSize()) {
offsetsMap.forEach { offset ->
val image = markersMap[offset.key]?.bitmap?.asImageBitmap()
image?.let {
drawImage(
image = image,
topLeft = offset.value.value
)
}
}
}
}
Моя проблема: значения маркеров, найденные в LaunchedEffect, не соответствуют значениям, полученным из потока: если я получаю из потока, например. Offset(400,300), я помещаю его в маркерыMap по ключу x, получаю запись .
Но во время цикла запуска эффекта я найдите совершенно другое значение из той же записи, не , а, скажем, , значение выглядит случайным или очень старым и остается неизменным во многих случаях, скажем, я обновляю 20 раз запись из потока, а из LaunchedEffect всё то же (неправильное) значение. Это означает, что анимация смещения будет начинаться с одной и той же точки много раз!
В результате анимация представляет собой своего рода цикл, начиная с одной и той же начальной точки смещения и повторяя один и тот же путь снова и снова.Я думаю, что проблема сложна, и именно по этой причине чатгпт не может так сильно помочь. Любой намек будет иметь огромную ценность. Заранее спасибо
РЕДАКТИРОВАТЬ
Как указано в комментариях ниже, это специально устраняет проблему (помещая всю логику анимации в поток получателя):
receivedFlow.value?.let { received ->
coroutineScope.launch {
withContext(Dispatchers.Default) {
handleDenmAlertData(received.denmAlertData, viewModel)
nativeAnimationManager?.let { nativeAnimationManager ->
val map = nativeAnimationManager.mapboxMap
val point = Point.fromLngLat(received.lastLongitude, received.lastLatitude)
val projected = map.pixelForCoordinate(point)
if (!markersMap.containsKey(received.stationId)) {
markersMap[received.stationId] = RoadUserMarker(
stationId = received.stationId,
prevOffset = Offset(
x = projected.x.toFloat(),
y = projected.y.toFloat()
),
point = point,
stationType = received.stationType,
bitmap = findBitmap(received),
nextOffset = null,
animatedOffset = null,
lastUpdateTime = System.currentTimeMillis()
)
}
else {
markersMap[received.stationId]?.let {marker ->
marker.nextOffset?.let {
marker.prevOffset = it
println("Current offset***: " + markersMap[received.stationId]?.prevOffset)
}
marker.nextOffset = Offset(projected.x.toFloat(), projected.y.toFloat())
marker.animatedOffset = Animatable(marker.prevOffset, Offset.VectorConverter)
marker.animatedOffset!!.animateTo(marker.nextOffset!!, tween(900))
}
}
}
}
}
Canvas(modifier = Modifier.fillMaxSize()) {
markersMap.forEach { markerEntry ->
val image = markerEntry.value.bitmap.asImageBitmap()
markerEntry.value.animatedOffset?.let {
drawImage(
image = image,
topLeft = it.value
)
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/785 ... n-properly