과제를 진행하며 기존에 Bottom Navigation
과 Navigation graph
를 연결해 화면을 전환하는 방식을 사용했었는데, 새로운 Fragment
로 전환시 어떤 Fragment
에서 이동했는지에 따라 다른 화면으로 이동해야하는 경우가 생겼다.
그래서 연동되어있던 Bottom Navigation
을 해제하고 이동하기 전의 Fragment
가 무언지에 따라 다른 화면으로 돌아갈 수 있도록 setOnItemSelectedListener
을 사용했다.
어떻게 이전의 Fragment
를 알아낼 수 있을까 생각하다가 Fragment
가 전환되면 이전의 Fragment
는 BackStack
에 저장된다는걸 기억하고, BackStack
이 생성된 Fragment
를 알아내기위해 다양한 시도를 해보며 알아냈다.
(이번 글의 모든 내용은 nav graph
를 사용했을 때를 기준으로 한다. 물론 BackStack
에 대한 내용은 사용하지 않아도 겹칠 수 있다.)
Fragment
는 화면에 생성되면 BackStack
에 추가 된다.
좀 더 자세히 보자면 Fragment
가 트랙젝션 되면서 생성된 정보를 모아 BackStack Entry
로 만들고 , 만들어진 BackStack Entry
가 BackStack
에 추가되는 방식이다.
그래서 navController
를 통해 currentBackStack
으로 현재 백스택을 확인하면, 현재 Fragment
까지 도달하기위해 생성된 모든 BackStack Entry
목록을 확인할 수 있다.
따라서 BackStack
에 저장된 Entry
들을 확인해 내가 이전에 어떤 Fragment
에 있었는지를 확인하는게 가능해진다.
백스택과 엔트리를 확인하는것 부터 차근차근 살펴보면
// nav 컨트롤러를 가져오기 위해 NavHost프래그먼트를 불러온다.
val navHost = supportFragmentManager.findFragmentById(R.id.nav_host) as NavHostFragment
// 가져온 Nav컨트롤러로 현재 백스택 목록을 확인한다.
navHost.navController.currentBackStack
// 가장 상단에 있는 백스택 엔트리 (현재 화면에 나오고 있는거)를 확인한다.
navHost.navController.currentBackStackEntry
위와같이 현재 백스택과 엔트리를 확인할 수 있다.
백스택에서 각각의 백스택 엔트리에는 4가지 정보가 저장되며, 이를 확인해 해당 백스택이 어떤 곳에서 생성되어있는지 확인이 가능하다.
- BackStack Entry의 ID
: Entry마다 각각 고유한 ID값을 가진다. 따라서 같은 Fragment라고 해도 새롭게 생성된다면 다른 EnrtyID를 가지며 새롭게 생성된다.
(백스택에 같은 화면이 2개 존재하게 될 수 도 있음)
- BackStack의 destination(종착지)
: Entry가 생성된 곳이자 해당 Entry가 백스택의 최상단으로 올라가 화면에 노출되야 할 경우 나타날 Fragment가 어떤 것인지 알려주는 종착지이다. 이 값을 확인해 현재Fragment
이전의 Fragment가 어떤 Fragment였는지 확인이 가능하다.
- label
: Navi graph에서 지정한 라벨 정보가 붙는다.
- class
: 해당 Fragment가 어떤 클래스를 상용해 생성된 것인지 나타낸다.
백스택 엔트리에는 위와같은 값들이 저장되어 있기때문에 이전의 엔트리만 확인이 가능하다면 2~3
번의 항목중 무엇을 사용하더라도 이전 화면이 어디였는지 확인이 가능하다.
currentBackStackEntry
에서 현재의 엔트리를 가져온다면 previousBackStackEntry
에서는 현재 화면으로 이동되기 이전에 생성된 엔트리의 정보를 가져올 수있다.
즉, previousBackStackEntry
로 불려온 엔트리정보를 확인하면 이전 화면이 어떤것인지 확인이 가능해진다.
// 이전 화면의 destination ID값을 가져온다.
val prevDestination = navHost.navController.previousBackStackEntry?.destination?.id
// 각 Fragment의 destination ID값을 가져온다.
val mainFragment = navHost.navController.findDestination(R.id.menu_main)?.id
val searchFragment = navHost.navController.findDestination(R.id.menu_search)?.id
if (prevDestination == mainFragment) {
//만약 이전의 Fragment가 Main Fragment라면 이 코드가 실행된다.
}
if (prevDestination == searchFragment) {
//만약 이전의 Fragment가 Search Fragment라면 이 코드가 실행된다.
}
위와 같은 방법으로 Bottom Navigation
에 setOnItemSelectedListener
를 설정해 각 버튼이 어디에서 눌리는지에 따라 다른 로직을 실행할 수 있도록 만들었다.
너무 재미있어
근데!
너무 힘들어
하지만!
흥미진진한거같아
그러나!
피로에 쩔어서 죽겠어
하우에버!
문제를 해결할때마다 짜릿해
벗!
지금당장 쓰러져도 이상할게 없을 만큼 지쳤어
네버더레스!
원하는걸 모두 만들어서 쾌감이 최고야...
진짜... 내마음은 뭘까...?