Android/Jetpack Compose

Jetpack Compose LaunchedEffect를 이용한 CountDown 기능 구현

loppav6 2022. 10. 27. 10:38

흔히 볼 수 있는 "N초 후에 화면이 닫힙니다"를 LaunchedEffect를 이용하여 간단하게 구현이 가능하다.

이전에 포스팅한 AlertDialog를 재활용하여 알럿창이 N초간 닫히지 않을 경우 자동으로 닫히도록 구현해보자.

(Jetpack Compose AlertDialog 포스팅: https://loppav6.tistory.com/6?category=975534)

 

먼저 LaunchedEffect에 대해서 알아보자.

LaunchedEffect는 코루틴 스코프에서 실행되는 컴포저블이다.

보통 suspend 함수를 취소하고 다시 실행해야할 때 사용한다.

그렇다면 rememberCoroutineScope를 생성해서 사용하면 되지 않을까?

아래와 같은 에러가 발생한다. LaunchedEffect를 사용하라고 친절히 알려준다.

val scope = rememberCoroutineScope()
scope.launch {
    //error: Calls to launch should happen inside a LaunchedEffect and not composition
}

LaunchedEffect 블럭안에 while 무한루프를 돌리고 delay 1초마다 실행시켜주도록 하면

CountDown기능을 간단하게 구현할 수 있다.

LaunchedEffect(Unit) {
    while(true) {
        delay(1.seconds)
    }
}

이전에 포스팅한 Jetpack Compose AlertDialog의 소스를 가져와서 구현해보자.

(Jetpack Compose AlertDialog 포스팅: https://loppav6.tistory.com/6?category=975534)

카운트는 3초로 설정하고 3초 후 AlertDialog가 닫히도록 구현하였다.

@Composable
fun MainView() {
    Column {
        val showDialog = remember { mutableStateOf(false) }
        Button(onClick = { showDialog.value = true }) {
            Text(text = "AlertDialog 호출")
        }
        if (showDialog.value) {
            var sec by remember { mutableStateOf(3) }
            var contents by remember { mutableStateOf("${sec}초 후 닫힙니다.") }

            LaunchedEffect(Unit) {
                while (true) {
                    sec--
                    delay(1.seconds)
                    if (sec > 0) contents = "${sec}초 후 닫힙니다."
                }
            }

            if (sec < 0) showDialog.value = false

            AlertDialog(onDismissRequest = {
                showDialog.value = false
            }, confirmButton = {
                Button(onClick = { showDialog.value = false }) {
                    Text(text = "확인")
                }
            }, title = {
                Text(text = "타이틀")
            }, text = {
                Text(text = contents)
            }, dismissButton = {
                Button(onClick = { showDialog.value = false }) {
                    Text(text = "취소")
                }
            })
        }
    }
}

 

결과는 아래와 같다.