The following sample code is from a website, the function of the code is to display a clock. The author use the code LaunchedEffect(Unit) { while (true) {... delay(1000)} }
to recomposition UI every second just like a clock.
A: Will the code LaunchedEffect(Unit){ while (true) {...} }
generate many coroutines? will it cause the App crash?
B: Will the variable such as val second = remember{...}
be locked when many coroutines try to assign new value to it?
class ClockActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Column(modifier = Modifier.fillMaxSize()) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.5f)
) {
Clock()
}
}
}
}
}
@Composable
fun Clock() {
val hour = remember { mutableStateOf(0f) }
val minute = remember { mutableStateOf(0f) }
val second = remember { mutableStateOf(0f) }
LaunchedEffect(Unit) {
while (true) {
val cal = Calendar.getInstance()
hour.value = cal.get(Calendar.HOUR).toFloat()
minute.value = cal.get(Calendar.MINUTE).toFloat()
second.value = cal.get(Calendar.SECOND).toFloat()
delay(1000)
}
}
val diameter = 200.dp
val color1 = Color.Black
Canvas(
modifier = Modifier
.size(diameter, diameter)
) {
val outCircleR = size.width / 2
val innerCircleR = (size.width / 2 * 0.8).toFloat()
drawCircle(color = color1, radius = size.width * 0.02f)
drawCircle(color = color1, radius = outCircleR, style = Stroke(4f))
drawCircle(
color = color1,
radius = innerCircleR,
style = Stroke(2f)
)
translate(size.width / 2, size.height / 2) {
...
val secondLength = outCircleR * 0.9f
val secondAngle = second.value.div(60) * 360
drawLine(
color = color1,
start = Offset.Zero,
end = Offset(
(secondLength * cos(secondAngle * Math.PI / 180)).toFloat(),
(secondLength * sin(secondAngle * Math.PI / 180)).toFloat()
),
strokeWidth = 2f,
cap = StrokeCap.Round
)
...
}
}
}
}
CodePudding user response:
A: Will the code LaunchedEffect(Unit){ while (true) {...} } generate many coroutines? will it cause the App crash?
No, it won't create many coroutines. A single LaunchedEffect
launches a single coroutine and:
- cancels it and re-launches a coroutine when any of
LaunchedEffect
key
parameters change. - cancels it when
LaunchedEffect
leaves the composition
Since in your code example the key
parameter is set to Unit
it never changes, so case 1. will never happen in your case. There will be only one coroutine started by LaunchedEffect
and it will run until the composable is part of the composition.
Additionally the code inside the coroutine will only be run once per second. Between re-runs the coroutine will be suspended.
B: Will the variable such as
val second = remember{...}
be locked when many coroutines try to assign new value to it?
Since in your case only one coroutine assigns a new value to it you don't have to worry about this.
I don't know how MutableState
works when there are multiple coroutines accessing it, but assigning a new value should not be problematic even if there are multiple coroutines doing it at the same time, so you would not need synchronization for that. The synchronization becomes important if you would have more than one coroutine manipulating the value in such a way, where another coroutine running in between that manipulation, would leave the value in an invalid state.