Jetpack Navigation
Jetpack Navigation의 장점:
- 직관적인 Navigation 관리: Navigation Graph를 통해 앱의 Navigation 구조를 시각적으로 파악하고 관리할 수 있습니다.
- 유형 안전한 데이터 전달: Safe Args를 사용하여 Fragment 간에 데이터를 안전하게 전달할 수 있습니다.
- 간편한 Fragment 이동:
navigate()
와popBackStack()
메서드를 사용하여 Fragment 이동을 간편하게 처리할 수 있습니다. - deep link 지원: 앱 외부의 링크를 통해 특정 Fragment로 바로 이동할 수 있습니다.
navigate()
호출 시 상세 동작 과정
Action 검색:
NavController
는 전달받은 action ID를 기반으로 Navigation Graph에서 해당 Action을 찾습니다.Action에는 이동할 목적지 Fragment (Destination) 정보와 전달할 데이터(Arguments) 등이 포함되어 있습니다.
Destination 확인:
Action에서 지정된 Destination Fragment의 유형을 확인합니다.
Fragment, Activity, DialogFragment, Custom Destination
등 다양한 유형의 Destination을 지원합니다.
현재 상태 저장 (선택 사항):
saveState()
메서드를 통해 현재 Fragment의 상태를 저장할 수 있습니다.이는 Fragment가 다시 표시될 때 이전 상태를 복원하기 위해 필요합니다.
Argument 전달 (선택 사항):
Safe Args를 사용하여 Destination에 정의된 Argument를 전달할 수 있습니다.
Argument는 Bundle 형태로 전달되며, Destination Fragment에서
arguments
속성을 통해 받을 수 있습니다.
FragmentTransaction 생성:
NavController
는 FragmentManager를 사용하여 FragmentTransaction을 생성합니다.FragmentTransaction은 Fragment 추가, 삭제, 교체 등 Fragment 상태 변경 작업을 정의합니다.
FragmentTransaction 실행:
생성된 FragmentTransaction을 실행하여 새로운 Destination Fragment를 화면에 표시합니다.
이때, 사용자가 정의한 Transition 애니메이션이나 기본 애니메이션이 적용될 수 있습니다.
Lifecycle Callback 호출:
Fragment 생명주기(
onCreate
,onViewCreated
,onResume
등)에 따라 필요한 콜백 메서드가 호출됩니다.이를 통해 Fragment 초기화, 데이터 로드, UI 업데이트 등의 작업을 수행할 수 있습니다.
BackStack 업데이트 (선택 사항):
navigate()
메서드에addToBackStack
옵션을true
로 설정하면, 현재 Fragment가 BackStack에 추가됩니다.사용자가 뒤로 가기 버튼을 누르면 BackStack에 저장된 Fragment가 다시 표시됩니다.
추가 고려 사항:
- ViewModel 공유:
by activityViewModels()
또는by navGraphViewModels()
를 사용하여 ViewModel을 공유하고, Fragment 간에 데이터를 안전하게 전달할 수 있습니다. - Deep Link:
navigate()
메서드에 URI를 전달하여 Deep Link를 통해 특정 Destination으로 이동할 수 있습니다. - Navigation Listener:
NavController.OnDestinationChangedListener
를 등록하여 Destination 변경 이벤트를 감지하고 추가 작업을 수행할 수 있습니다.
FragmentManager 를 통한 Transaction
add: Host Activity의 생명주기에 Fragment 생명주기 추가, add된 Fragment는
onAttach ~ onResume
까지 호출- Add a fragment to the activity state.
remove:
onPause ~ onDetach
까지 호출, Fragment가 메모리에서 제거됨.- Remove an existing fragment. If it was added to a container, its view is also removed from that container.
replace:
replace()
함수 인자로 지정된 Fragment를 제외한 나머지 모든 프래그먼트가remove
- (나머지 Fragment는
onDetach
까지 호출, 지정된 Fragment는onAttach ~ onResume
)
- (나머지 Fragment는
show / hide: 기본적으로
add
된 Fragment를 대상으로 View를 보이게 하거나 감춤.(visibility
변경)attach: 대상 Fragment의
onCreateView ~ onResume
까지 호출- Re-attach a fragment after it had previously been detached from the UI with detach(android.app.Fragment). This causes its view hierarchy to be re-created, attached to the UI, and displayed.
detach: 대상 Fragment의
onPause ~ onDestroyView
까지 호출- Detach the given fragment from the UI. This is the same state as when it is put on the back stack: the fragment is removed from the UI
backStack
에서 없어지면(pop되면),onDestoryView ~ onDetach
까지 호출backStack
에 존재하면,onDestoryView
까지만 호출, 다시backStack
최상단에 특정 Fragment가 존재하면,onCreateView
부터 호출A -> B로
naviagte()
시, B가 Create 되고, A가 Destory 됨. (선 Create, 후 Destory)
popUpTo
속성으로 특정 Fragment를 지정하면, 그 사이의NavBackStackEntry
은 backStack에서 제거된다.popUpToInclusive
속성을true
로 설정해주면, backStackpopUpTo
로 지정된NavBackStackEntry
은 제거된다.popUpToInclusive
값을 지정하지 않으면,popUpToInclusive=false
와 같다.false가 default