[TIL] Fragment와 Back stack

박봉팔·2024년 2월 1일
0
post-thumbnail

Back stack

과제를 진행하며 기존에 Bottom NavigationNavigation graph를 연결해 화면을 전환하는 방식을 사용했었는데, 새로운 Fragment로 전환시 어떤 Fragment에서 이동했는지에 따라 다른 화면으로 이동해야하는 경우가 생겼다.

그래서 연동되어있던 Bottom Navigation을 해제하고 이동하기 전의 Fragment가 무언지에 따라 다른 화면으로 돌아갈 수 있도록 setOnItemSelectedListener을 사용했다.

어떻게 이전의 Fragment를 알아낼 수 있을까 생각하다가 Fragment가 전환되면 이전의 FragmentBackStack에 저장된다는걸 기억하고, BackStack이 생성된 Fragment를 알아내기위해 다양한 시도를 해보며 알아냈다.
(이번 글의 모든 내용은 nav graph를 사용했을 때를 기준으로 한다. 물론 BackStack에 대한 내용은 사용하지 않아도 겹칠 수 있다.)


BackStack? BackStack Entry?

Fragment는 화면에 생성되면 BackStack에 추가 된다.

좀 더 자세히 보자면 Fragment가 트랙젝션 되면서 생성된 정보를 모아 BackStack Entry로 만들고 , 만들어진 BackStack EntryBackStack에 추가되는 방식이다.

그래서 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

위와같이 현재 백스택과 엔트리를 확인할 수 있다.


BackStack Entry

백스택에서 각각의 백스택 엔트리에는 4가지 정보가 저장되며, 이를 확인해 해당 백스택이 어떤 곳에서 생성되어있는지 확인이 가능하다.

  1. BackStack Entry의 ID
    : Entry마다 각각 고유한 ID값을 가진다. 따라서 같은 Fragment라고 해도 새롭게 생성된다면 다른 EnrtyID를 가지며 새롭게 생성된다.
    (백스택에 같은 화면이 2개 존재하게 될 수 도 있음)

  2. BackStack의 destination(종착지)
    : Entry가 생성된 곳이자 해당 Entry가 백스택의 최상단으로 올라가 화면에 노출되야 할 경우 나타날 Fragment가 어떤 것인지 알려주는 종착지이다. 이 값을 확인해 현재 Fragment이전의 Fragment가 어떤 Fragment였는지 확인이 가능하다.

  3. label
    : Navi graph에서 지정한 라벨 정보가 붙는다.

  4. class
    : 해당 Fragment가 어떤 클래스를 상용해 생성된 것인지 나타낸다.

백스택 엔트리에는 위와같은 값들이 저장되어 있기때문에 이전의 엔트리만 확인이 가능하다면 2~3번의 항목중 무엇을 사용하더라도 이전 화면이 어디였는지 확인이 가능하다.


previousBackStackEntry

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 NavigationsetOnItemSelectedListener를 설정해 각 버튼이 어디에서 눌리는지에 따라 다른 로직을 실행할 수 있도록 만들었다.


오늘은 어땠나요?

너무 재미있어

근데!

너무 힘들어

하지만!

흥미진진한거같아

그러나!

피로에 쩔어서 죽겠어

하우에버!

문제를 해결할때마다 짜릿해

벗!

지금당장 쓰러져도 이상할게 없을 만큼 지쳤어

네버더레스!

원하는걸 모두 만들어서 쾌감이 최고야...


진짜... 내마음은 뭘까...?

profile
개발 첫걸음! 가보자구!

0개의 댓글