마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Compose navigate 질문입니다.

0 추천
MainActivity 안에 NavHost 로 Screen1, Screen2, Screen3 을 셋팅해놨습니다.

 

Screen1 진입부에 로그를 찍어둔 후, 버튼 하나를 만들어 onClick으로 navController.navigate("Screen2") 를 할 경우 Screen2 로 이동이 되는데 문제는 Screen1에 찍어둔 로그가 한번찍히고 이동이 되더라고요.

그리고 다시 백버튼을 누르면 로그가 두번찍힙니다.

로그가 찍히는 이유가 뭔가요?
콜벳 (7,150 포인트) 님이 3월 15일 질문

1개의 답변

0 추천
 
채택된 답변
그건 님의 코드가 Compose function이 다시 호출되도록 되었을 가능성이 매우 높습니다. 이걸 recomposition이라고 부르는데, 복잡하지만 Compose의 핵심 개념 중의 하나라서 Compose를 사용할 때는 잘 숙지해야하는 개념입니다. Compose function에 사용되는 값들 중에 변경이 생기는 것이 있으면 (예를 들면, MutableState), Compose function이 다시 호출되게 됩니다. 사용하신 코드를 잘 보시면 recomposition을 만드는 부분이 있을 겁니다.
spark (227,830 포인트) 님이 3월 17일 답변
콜벳님이 3월 20일 채택됨
감사합니다!

제가 아래와 같이 소스를 짰는데 문제는 a b 스크린이 순차적으로 뜨고 3초뒤 b 스크린은 사라집니다
다만 a스크린도 리컴포지션이 되는데 어떻게 막는걸까요? b만 숨기고 a는 리로딩이 안되게 하고싶습니다 로그를 찍으면
ascreen
bscreen
3초 두ㅣ ascrren 이렇게 찍히네요
val visible = remember { mutableStateOf(true)}
Box () {
  AScreen()
  BScreen(visible.value)
  LaunchedEffect(Unit) {
      visible.value = finishB()
  }
 }
}

private suspend fun finishB(): Boolean {
  delay(3000)
  retuen false
위의 구조면 당연히 AScreen(), BScreen() 호출되겠죠?
Compose navigation을 사용하셔서  라우트에 따라 스크린을 분리하세요.

@composable("DestinationA") {
        AScreen()
}

@composable("DestinationB") {
        BScreen()
}

navController.navigate("DestinationA")
navController.navigate("DestinationB")
와 같이 화면이동하시구요. 자세한 사용법은 개발자 문서에서 Jetpack Compose Navigation 가이드를 참조하세요.
다시 한번 답변 감사합니다.
위의 내용은 A와 B 전부 호출이 되는게 맞는데 3초 후 B 스크린을 닫는 과정에서 A 스크린까지도 리컴포지션이 된다는게 문제입니다.

다만 구성하려는 부분은 A 화면이 뜬 상태로 로드를 완료가 되면 B 화면이 닫히는 구조입니다.
그래서 한 부분에 같이 해둔상태고 navController 로 할 수 없었습니다.

xml로 따지면 AScreenLayout 과 BScreenLayout 을 Frame or  Relative 로 겹쳐 놓은 다음에 로딩이 완료되면 BScreen GONE 처리 하는거라고 생각하시면 됩니다..
그런 경우라면 조건을 걸어서 해당 @Composable만 그려지게 하시는게 맞을 것 같습니다.
Box {
 // visible.value 조건에 따라서
    if (!visible.value) {
        navController.navigate(...) // or navController.popBackStack()
    } {
        AScreen()
        BScreen()
    }
}

LaunchedEffect(Unit) {
      visible.value = finishB()
}
...