Android API26(Oreo)下修改MutableState后Composable不重组问题
不同Android API级别下Compose重组异常问题
现象差异
设备1:Android API 33(Android 13)
代码运行符合预期,camera2D的值被修改后,Composable会触发重组。设备2:Android API 26(Android Oreo)
代码运行不符合预期,camera2D的值已被修改,但Composable未触发重组。
复现代码
import androidx.compose.foundation.Canvas import androidx.compose.foundation.gestures.awaitEachGesture import androidx.compose.foundation.gestures.awaitFirstDown import androidx.compose.foundation.gestures.calculatePan import androidx.compose.foundation.gestures.calculateZoom import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.withTransform import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp @Composable fun EditorScreen() { BoxWithConstraints { val dpToPxRatio = with(LocalDensity.current) { 1.dp.toPx() } val camera2D = remember(key1 = maxWidth, key2 = maxHeight) { mutableStateOf( Camera2D( translation = Translation2D( x = (maxWidth.value * dpToPxRatio) / 2f, y = (maxHeight.value * dpToPxRatio) / 2f ), scale = Scale2D( scaleX = 1f, scaleY = 1f ) ) ) } val editorObjects = remember { mutableStateListOf( SquareEditorObject2D( translation = Translation2D(x = 0.0f, y = 0.0f), size = Size2D(width = 350.0f, height = 580.0f), scale = Scale2D(scaleX = 1.0f, scaleY = 1.0f), rotation = Rotation2D(zRotationDegrees = 0f), color = Color.Blue ), SquareEditorObject2D( translation = Translation2D(x = 0.0f, y = 0.0f), size = Size2D(width = 350.0f, height = 580.0f), scale = Scale2D(scaleX = 1.0f, scaleY = 1.0f), rotation = Rotation2D(zRotationDegrees = 45f), color = Color.Green ), SquareEditorObject2D( translation = Translation2D(x = 0.0f, y = 0.0f), size = Size2D(width = 350.0f, height = 580.0f), scale = Scale2D(scaleX = 1.0f, scaleY = 1.0f), rotation = Rotation2D(zRotationDegrees = 135f), color = Color.Red ) ) } Canvas( modifier = Modifier .fillMaxSize() .pointerInput(key1 = Unit) { awaitEachGesture { awaitFirstDown() do { val currentCamera2D = camera2D.value val event = awaitPointerEvent() val pointerCount = event.changes.count() if (pointerCount == 1) { val dragAmount = event.calculatePan() camera2D.value = currentCamera2D.copy( translation = Translation2D( x = currentCamera2D.translation.x + dragAmount.x, y = currentCamera2D.translation.y + dragAmount.y ) ) } else if (pointerCount > 1) { val eventZoom = event.calculateZoom() camera2D.value = currentCamera2D.copy( scale = Scale2D( scaleX = currentCamera2D.scale.scaleX * eventZoom, scaleY = currentCamera2D.scale.scaleY * eventZoom ) ) } } while (event.changes.any { it.pressed }) } } ) { withTransform( { translate( left = camera2D.value.translation.x, top = camera2D.value.translation.y ) scale( scaleX = camera2D.value.scale.scaleX, scaleY = camera2D.value.scale.scaleY ) } ) { for (editorObject in editorObjects) { withTransform( { translate( left = editorObject.translation.x - editorObject.pivot.x, top = editorObject.translation.y - editorObject.pivot.y ) rotate( degrees = editorObject.rotation.zRotationDegrees, pivot = Offset( x = editorObject.size.width / 2f, y = editorObject.size.height / 2f ) ) scale( scaleX = editorObject.scale.scaleX, scaleY = editorObject.scale.scaleY, pivot = Offset( x = editorObject.size.width / 2f, y = editorObject.size.height / 2f ) ) } ) { drawRect( color = editorObject.color, size = Size( width = editorObject.size.width, height = editorObject.size.height ) ) } } } } } } data class Translation2D(val x: Float, val y: Float) data class Size2D(val width: Float, val height: Float) data class Scale2D(val scaleX: Float, val scaleY: Float) data class Rotation2D(val zRotationDegrees: Float) data class SquareEditorObject2D( val translation: Translation2D = Translation2D(x = 0f, y = 0f), val size: Size2D, val scale: Scale2D = Scale2D(scaleX = 1f, scaleY = 1f), val rotation: Rotation2D = Rotation2D(zRotationDegrees = 0f), val color: Color ) { val pivot = Translation2D( x = (size.width / 2f), y = (size.height / 2f) ) } data class Camera2D( val translation: Translation2D = Translation2D(x = 0f, y = 0f), val scale: Scale2D = Scale2D(scaleX = 1f, scaleY = 1f), val rotation: Rotation2D = Rotation2D(zRotationDegrees = 0f) )
依赖版本
implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") implementation("androidx.activity:activity-compose:1.7.2") implementation(platform("androidx.compose:compose-bom:2023.03.00")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3")
内容的提问来源于stack exchange,提问作者Augusto Carmo
相关产品推荐
相关产品推荐

