아찔했던 기억
이 그래프는 로그인와 회원가입 그리고 비밀번호 재설정에 관한 그래프 입니다.
- 회원가입시 비밀번호 설정에서 뒤로가면 인증번호 확인이 아닌 이메일 인증 화면으로 돌아가고 싶었습니다.
- 가입이 완료되면 회원가입에 관한 스택을 비우고 로그인 화면을 넘어가고 싶었습니다.
- 비밀번호 재설정시 비밀번호 재설정 화면에서 뒤로가면 인증번호 확인이 아닌 이메일 인증 화면으로 돌아가고 싶었습니다.
- 비밀번호 재설정이 완료되면 재설정에 관한 스택을 비우고 로그인 화면으로 넘어가고 싶었습니다.
지금 보면 그렇게 어려운 처리는 아니었습니다. 하지만 그 당시에는 popUpTo, popUpToInclusive 등 관련 옵션이나 함수들을 잘 몰랐기에 어려워했던 기억이 납니다.😥
그럼 자주 사용되는 popUpTo,popUpToInclusive 을 위의 상황에 도입해보고 다른 함수나 옵션이 있는지 확인해 봅시다.
Navigation과 back stack
먼저 가볍게 공식문서부터 살펴봅시다!
Jetpack Navigation에서는 navigate()가 호출될 때마다 스택의 최상단으로 해당 destination을 올립니다. 해당 스택을 위로 올릴 땐 navigateUp(), 뒤로갈때는 popBackStack()이 호출됩니다.
다이얼로그의 경우 FloatingWindow 인터페이스를 Implement하는데 이는 백 스택의 다른 목적지 위에 올라갑니다. 따라서 하나 이상의 FloatingWindow는 백 스택의 맨 위에만 존재할 수 있습니다. FloatingWindow가 없는 목적지로 갈 경우 자동으로 모든 FloatingWindow는 스택 최상단에서 pop 됩니다.
만약 유저가 위 백스택에서 다른 다이얼로그로 navigate 한다면 백스택 최상단에 추가됩니다.
이 상황에서 만약 non-floating한 destination으로 navigate한다면 모든 FloatingWindow들은 백스택 최상단에서 pop되고 non-floating한 destination이 최상단으로 쌓이게 됩니다.
popUpTo 와 popUpToInclusive
popUpTo와 popUpToInclusive는 대상을 일일이 pop하지 않고 관련된 모든 대상을 백스택에서 pop할 수 있게 해줍니다.
<action>태그안에 app:popUpTo와 app:popUpToInclusive를 추가하여 편하게 사용할 수 있습니다
app:popUpTo=”destination”를 추가하면 action이 실행될 때 백 스택의 destination까지의 stack들이 pop 됩니다.
app:popUpToInclusive=”true”를 추가하면 pupUpTo에 지정된 destination을 포함하여 stack들이 pop 됩니다.
예시 그래프를 통해 설명해보겠습니다.
프래그먼트 1, 2, 3, 4, 5 가 순환되는 흐름입니다. 여기서 3 → 4로 넘어가는 action에 popUpTo=one을 해보겠습니다.
one -> two -> three 로 이동하고 one 까지의 two, three는 pop이 되어 스택에는 one과 four만 남게 됩니다. 따라서 one 에서 뒤로가기를 누르면 앱이 종료됩니다.
popUpToInclusive=true 를 추가하면 one 또한 스택에서 사라집니다
one -> two -> three 로 이동하고 one, two, three 모두 스택에서 pop 되어 four 화면에서 뒤로가기를 누르면 앱이 종료됩니다.
popUpTo에 설정된 destination이 백 스택에 여러개 쌓여 있을 때 최상단의 destination이 설정되므로 순환이 되는 흐름에서 돌아오는 action에 popUpToInclusive=true를 설정해주지 않으면 똑같은 화면이 두개가 쌓이게 됩니다.
popUpTo와 비슷한 기능을 popBackStack(destinationId, inclusive)를 통해 사용할 수 있습니다. 특정 화면에서 뒤로가기를 눌렀을 때 이전의 작업들을 취소하고 첫화면으로 돌아가는 경우에 블로그 위에서 언급한
‘회원가입시 비밀번호 설정에서 뒤로가면 인증번호 확인이 아닌 이메일 인증 화면으로 돌아가고 싶었습니다.’
의 경우를 예로 들 수 있습니다.
popBackStack()에 아무 옵션을 주지 않으면 해당 화면만 pop됩니다. 하지만 옵션을 추가하면 popUpTo와 비슷하게 사용할 수 있습니다.
destination까지의 stack들을 pop 해주는데 마찬가지로 inclusive 옵션을 주어 포함시켜서 pop 할 지를 정할 수 있습니다.
NavOptions
또한 navigate(resId, args, navOptions)에서 navOptions을 통해 스택을 관리할 수 있습니다.
NavOptions를 보면 여러 상태들이 있는데 스택과 관련된 singleTop, popUpToId, popUpToInclusive, popUpToSaveState등을 볼 수 있습니다.
각각의 상태의 초기값은 아래와 같습니다.
각 상태들은 Builder()를 통해 세팅할 수 있습니다.
- singleTop : 싱글탑은 최상단에 있는 destination과 전환 될 destination이 같을 때, 새로운 인스턴스를 생성하지 않고 스택에 있는 destination을 재사용하는것을 의미하는데 setLaunchSingleTop()을 통해 세팅이 가능합니다.
- popUpTo : popUpTo와 관련된 상태는 setPopUpTo()를 통해 세팅이 가능합니다. 사용 방법은 <action> 태그에 사용된 popUpTo와 동일합니다.
그럼 간단하게 활용해 봅시다.
five에서 one으로 돌아올 때 one위의 모든 스택들을 pop하려면 아래와 같은 코드로 구현할 수 있습니다.
돌아올 화면을 재사용하길 원한다면 singleTop을 true로 바꿔주면 됩니다.
State와 관련된 이야기는 아래서 짧게 다뤄보겠습니다.
popUpToSaveState 와 restoreSaveState
는 다음에~
마무리
예전의 아찔했던 추억을 떠올리며 다시한번 공부해 보았습니다.popUpTo와 popUpToInclusive만 사용해와서 그런지 알게된 것도 많았고 어려웠던 점도 많았습니다😥
또 Task와 관련된 글도 이어 쓰려고 했으나 너무 길어지는 거 같아 여기서 마무리하겠습니다👍
참고