시리즈

[Android] Navigation

20190605

Navigation



gradle에 navigation을 추가

https://developer.android.com/jetpack/androidx/releases/navigation#declaring_dependencies
위 링크로 들어가서 최신 버전을 확인하고 그래들(모듈)에 복사 붙여넣기를 하면 된다.
activity_main.xml 에 다음 xml 코드를 넣는다.


이렇게 하면 호스트가 추가된다
네비게이션 xml 로 들어가서 Design 탭을 확인해보자.
왼쪽에 HOST에 defaultNavHost로 지정해 준 프래그먼트가 추가되어 있다.


버튼들
버튼들

왼쪽 위에 버튼들이 보일 것이다. 제일 왼쪽 버튼을 눌러서 네비게이션에 프래그먼트를 추가할 수 있다.



프래그먼트 추가
프래그먼트 추가

4개의 프래그먼트를 추가한 모습이다. 왼쪽에 프래그먼트들이 보인다. 네비게이션 그래프에서 이런 노드들을 도착점(destination)이라고 한다.



프래그먼트 연결
프래그먼트 연결

constraint를 추가할 때와 같이 화살표를 끌어서 다른 쪽으로 연결할 수 있다. 이렇게 화살표를 연결하면 액션(action)이 만들어진다.


A-B-C-D
A-B-C-D

구분 편의를 위해 A B C D 를 나오게 했다.
액션은 만들어졌지만 이 액션을 실행할 이벤트를 지정해주어야 한다.
약간의 논란(?)은 있겠지만 이런 식의 코드가 코틀린과 자바에 모두에서 원활하게 돌아간다.
view.findNavController() 방식은 코틀린에서만 작동한다.
출처는 여기
A를 누르면 B가 나오고 하는 식으로 순서대로 A B C D 가 나오게 하면 된다.
코딩이 귀찮으니 코드를 다운받아서 확인해보자



D까지 올바르게 나오는지 확인해보자.

백 스택 관리

사실상 핵심 파트이다. 백 스택 관리를 원활하게 하려고 하는게 가장 큰 목적이다. 이 글은 독자가 스택 자료구조를 안다는 가정하에 쓰여졌다.
popUp 속성들을 이용해서 백 버튼을 눌렀을 때 어떻게 동작할 지를 설정할 수 있다.
D에서 백 버튼을 누르면 C로 돌아갈 것이다. 당연하다고 생각할 수도 있겠지만, 이건 액션이 일어날 때 안드로이드에서 백 스택을 자동으로 생성해주었기 때문이다.
마찬가지로 C에서는 B로, B에서는 A로, 마지막 A에서는 앱이 종료되는 것을 알 수 있다.
만약에 D버튼을 눌렀을 때 A로 돌아가고 싶으면 어떻게 할까?




C-D
C-D

C에서 D로 가는 액션을 클릭한 그림이다.
오른쪽 Attributes 탭에서 Pop Behavior 속성을 확인할 수 있다. 현재 none으로 되어있는 것을 알 수 있다.
이걸 blankFragment(즉, A)로 바꾸고 앱을 실행해보자.
D에서 백 버튼을 누르면 A로 돌아가고 다시 한번 백 버튼을 누르면 앱이 종료되게 된다.
이번에는 Inclusive 옵션을 체크한 뒤에 다시 앱을 실행해보자.
D에서 백 버튼을 누르면 앱이 종료되는 것을 확인할 수 있다.
기본 원칙은 아래 4가지 이다.
  1. 액션의 popUpTo 속성은 주어진 도착점이 나올 때까지 백 스택을 팝업한다.
  2. popUpToInclusive 속성이 false이거나 설정되지 않은 경우, popUpTo 는 지정된 도착점까지 모든 도착점들을 제거한다. 하지만 지정된 목적지는 백 스택에 들어있다.
  3. popUpToInclusive 속성이 true인 경우, popUpTo 속성은 주어진 목적지를 포함해서 모든 목적지들을 백 스택에서 제거한다.
  4. popUpToInclusive 속성이 true이고 popUpTo가 앱의 시작점으로 설정된 경우, action은 백 스택의 모든 도착점을 제거한다. 백 버튼을 누르면 바로 앱을 종료한다.
이렇게 글로만 보면 이해가 안되기 때문에 실험을 해보자.

약간의 실험들



복잡한 네비게이션 그래프
복잡한 네비게이션 그래프

좀 더 복잡한 백스택을 만들기 위해서 네비게이션 그래프를 위와 같은 형태로 바꿔보자. (물론 액션을 이벤트에 연결해주어야 한다.)
A -> B, C B -> C, D C -> D D -> A 이런 액션이 있는 그래프이다.

상황 1

A -> B -> D -> A -> C -> D
C->D 액션에 popUpTo를 BlankFragment2로 지정하고 D에서 백 버튼을 누르면 어떻게 될까?

상황 2

A -> C -> D -> A -> C -> D
백 스택이 있기 때문에 C에서 백 버튼을 누르면 A로 돌아간다. C가 B에서 왔는지 A에 왔는지를 백 스택으로 확인할 수 있다.
C->D 액션에 popUpTo를 BlankFragment2로 지정하고 D에서 백 버튼을 누르면 어떻게 될까?

상황 3

A -> B -> D -> A -> B -> D
B -> D 액션에 popUpTo를 BlankFragment로 지정하고 마지막 D에서 백 버튼을 누르면 어떻게 될까?

상황 4

A -> B -> D -> A -> B -> D
B -> D 액션에 popUpTo를 BlankFragment로 지정하고 popUpToInclusive를 true로 한 상태에서, 마지막 D에서 백 버튼을 누르면 어떻게 될까?

해답

상황 1의 경우

B로 돌아간다. (A -> B) 이 상태에서 두 번 백 버튼을 누르면 종료된다.

상황 2의 경우

백 스택에 BlankFragment2가 들어있지 않기 때문에 그냥 popUpTo 옵션이 지정되어 있지 않은 상황과 같이 동작한다. 바로 전 C로 돌아간다.

상황 3의 경우

화면은 A로 바뀐다. 이 A는 A -> B -> D -> A 의 마지막 A이다. 여기서 백 버튼을 누르면 D로 돌아가고, (A -> B -> D) 또 백 버튼을 누르면 B가 아니라 A로 돌아가는데 이것은 B -> D 액션의 popUpTo가 BlankFragment로 지정되어 있기 때문이다. 또 백 버튼을 누르면 종료된다.

상황 4의 경우

원칙 4에 의해서 백 스택에 모든 도착점들이 사라진다. 화면은 그대로 D를 나타내고 있고, 이 상태에서 백 버튼을 누르면 앱이 종료된다.

.

piano (press key Q)

Categories

flutter ( 82 ) dart ( 34 ) android ( 32 ) kotlin ( 11 ) plugin ( 8 ) provider ( 8 ) vim ( 7 ) bloc ( 6 ) iOS ( 6 ) state management ( 6 ) 플러터 ( 6 ) PS ( 5 ) algorithm ( 5 ) architecture ( 5 ) async ( 5 ) getx ( 5 ) java ( 5 ) API ( 4 ) BOJ ( 4 ) class ( 4 ) daily ( 4 ) git ( 4 ) golang ( 4 ) memo ( 4 ) riverpod ( 4 ) state ( 4 ) stream ( 4 ) test ( 4 ) web ( 4 ) widget ( 4 ) windows ( 4 ) HTTP ( 3 ) androidX ( 3 ) app state ( 3 ) context ( 3 ) crash ( 3 ) db ( 3 ) editor ( 3 ) error ( 3 ) extension ( 3 ) github ( 3 ) hive ( 3 ) ide ( 3 ) package ( 3 ) pubspec ( 3 ) python ( 3 ) syntax ( 3 ) vscode ( 3 ) app icon ( 2 ) await ( 2 ) chocolatey ( 2 ) consumer ( 2 ) cp949 ( 2 ) deployment ( 2 ) dev ( 2 ) flavor ( 2 ) gesture ( 2 ) globalkey ( 2 ) go ( 2 ) google ( 2 ) hack ( 2 ) js ( 2 ) json ( 2 ) key ( 2 ) keystore ( 2 ) list ( 2 ) listview ( 2 ) lock ( 2 ) mac ( 2 ) map ( 2 ) navigation ( 2 ) nosql ( 2 ) project ( 2 ) pub ( 2 ) recyclerview ( 2 ) rxdart ( 2 ) sdk ( 2 ) selector ( 2 ) setting ( 2 ) size ( 2 ) soc ( 2 ) synchronized ( 2 ) tdd ( 2 ) tip ( 2 ) version ( 2 ) viewmodel ( 2 ) vundle ( 2 ) webview ( 2 ) xcode ( 2 ) yaml ( 2 ) ( 2 ) 플러터 단점 ( 2 ) 16.0 ( 1 ) 2.0 ( 1 ) 2023 ( 1 ) AATP2 ( 1 ) ChangeNotifierProvider ( 1 ) Example ( 1 ) Guava ( 1 ) ImageReader ( 1 ) Mo's algorithm ( 1 ) OAuth2 ( 1 ) OpenGL ( 1 ) Oreo ( 1 ) ProgressBar ( 1 ) REST API ( 1 ) Trie ( 1 ) activity ( 1 ) adaptive ( 1 ) android P ( 1 ) android context ( 1 ) android11 ( 1 ) apktool2 ( 1 ) app exit ( 1 ) append ( 1 ) appicon ( 1 ) arkit ( 1 ) array ( 1 ) asciidoc ( 1 ) async * ( 1 ) async* ( 1 ) audio ( 1 ) authorization ( 1 ) await for ( 1 ) behaviorsubject ( 1 ) beta ( 1 ) binary ( 1 ) binarysearch ( 1 ) blender ( 1 ) book ( 1 ) bottomsheet ( 1 ) break ( 1 ) broadcast ( 1 ) browser ( 1 ) bubbles ( 1 ) bug ( 1 ) build ( 1 ) buildcontext ( 1 ) buildnumber ( 1 ) bundle ( 1 ) button ( 1 ) bytecode ( 1 ) cache ( 1 ) camera2 ( 1 ) cameramanager ( 1 ) cd ( 1 ) chrome ( 1 ) ci ( 1 ) circle ( 1 ) clean ( 1 ) clean architecture ( 1 ) cli ( 1 ) clip ( 1 ) clipboard ( 1 ) cloud ide ( 1 ) cmdlet ( 1 ) code ( 1 ) coding test ( 1 ) command ( 1 ) comparator ( 1 ) complexity ( 1 ) concurrency ( 1 ) conditional ( 1 ) const ( 1 ) constraint ( 1 ) constraintlayout ( 1 ) controlc ( 1 ) controlv ( 1 ) converter ( 1 ) copy ( 1 ) copy project ( 1 ) coupling ( 1 ) coverage ( 1 ) cp ( 1 ) css ( 1 ) cupertino ( 1 ) cursor ( 1 ) cv ( 1 ) data class ( 1 ) data structure ( 1 ) dataBinding ( 1 ) database ( 1 ) debounce ( 1 ) decompile ( 1 ) delegate ( 1 ) deno ( 1 ) design pattern ( 1 ) development ( 1 ) device ( 1 ) di ( 1 ) dialog ( 1 ) dio ( 1 ) drawable ( 1 ) drug ( 1 ) emmet ( 1 ) encoding ( 1 ) english ( 1 ) entries ( 1 ) environment ( 1 ) equality ( 1 ) equatable ( 1 ) euc-kr ( 1 ) euckr ( 1 ) exit ( 1 ) expand ( 1 ) expanded ( 1 ) export ( 1 ) extension method ( 1 ) facade ( 1 ) fake ( 1 ) field ( 1 ) figma ( 1 ) final ( 1 ) fixed ( 1 ) flutter pub ( 1 ) flutter web ( 1 ) flutter_inappwebview ( 1 ) flutter_test ( 1 ) flutterflow ( 1 ) fold ( 1 ) fonts ( 1 ) form ( 1 ) frame ( 1 ) future ( 1 ) gestureDetector ( 1 ) gestureRecognizer ( 1 ) gesturearena ( 1 ) get-command ( 1 ) get_cli ( 1 ) getbuilder ( 1 ) getx단점 ( 1 ) gitignore ( 1 ) glut ( 1 ) google fonts ( 1 ) gopath ( 1 ) goto ( 1 ) gradient ( 1 ) graphics ( 1 ) gvim ( 1 ) hackaton ( 1 ) hash ( 1 ) hashmap ( 1 ) hot reload ( 1 ) how to ( 1 ) html ( 1 ) i18n ( 1 ) icon ( 1 ) id ( 1 ) impeller ( 1 ) implementation ( 1 ) import ( 1 ) indicator ( 1 ) inkwell ( 1 ) interrupt ( 1 ) intl ( 1 ) introduction ( 1 ) io ( 1 ) isar ( 1 ) iterable ( 1 ) iteration ( 1 ) javascript ( 1 ) julia ( 1 ) juno ( 1 ) jupyter ( 1 ) kakaomap ( 1 ) keytool ( 1 ) korean ( 1 ) kotlin syntax ( 1 ) l10n ( 1 ) lambda ( 1 ) language ( 1 ) layer ( 1 ) layout ( 1 ) lineageOS ( 1 ) localkey ( 1 ) localtoglobal ( 1 ) long list ( 1 ) ls ( 1 ) mac osx ( 1 ) markdown ( 1 ) markup ( 1 ) material ( 1 ) method ( 1 ) microtask ( 1 ) migrate ( 1 ) mintlify ( 1 ) mock ( 1 ) module ( 1 ) monitor ( 1 ) moor ( 1 ) mouse ( 1 ) mouseregion ( 1 ) multiplatform ( 1 ) multiset ( 1 ) multithread ( 1 ) mutable ( 1 ) mvvm ( 1 ) new ( 1 ) node ( 1 ) nodejs ( 1 ) nosuchmethod ( 1 ) null-safety ( 1 ) numberformat ( 1 ) nvim ( 1 ) object ( 1 ) objectbox ( 1 ) objectkey ( 1 ) obx ( 1 ) online ide ( 1 ) operator ( 1 ) orientation ( 1 ) parabeac ( 1 ) parse ( 1 ) paste ( 1 ) path ( 1 ) pattern ( 1 ) pitfall ( 1 ) play store ( 1 ) pod ( 1 ) podfile ( 1 ) pointer ( 1 ) pointers ( 1 ) powershell ( 1 ) private ( 1 ) programming ( 1 ) pull to refresh ( 1 ) puzzle ( 1 ) pycharm ( 1 ) realitykit ( 1 ) recursion ( 1 ) reduce ( 1 ) reference ( 1 ) regex ( 1 ) regular expression ( 1 ) release note ( 1 ) renderbox ( 1 ) renderobject ( 1 ) repl ( 1 ) repository ( 1 ) response ( 1 ) rm ( 1 ) rotue ( 1 ) round ( 1 ) run ( 1 ) scope ( 1 ) scroll ( 1 ) search ( 1 ) server ( 1 ) serverless ( 1 ) service ( 1 ) sharp ( 1 ) singlerepo ( 1 ) singleton ( 1 ) sketch ( 1 ) sliver ( 1 ) sliverlist ( 1 ) snippets ( 1 ) sogae ( 1 ) sorting ( 1 ) source ( 1 ) sparse ( 1 ) sparse array ( 1 ) spec ( 1 ) split ( 1 ) sqflite ( 1 ) sqlite ( 1 ) sqrt decomposition ( 1 ) stateful ( 1 ) statefulwidget ( 1 ) step ( 1 ) stepper ( 1 ) string ( 1 ) stringbuffer ( 1 ) stringbuilder ( 1 ) studio ( 1 ) study ( 1 ) sub-directory ( 1 ) svn ( 1 ) swiftui ( 1 ) swipe to refresh ( 1 ) system_alert_window ( 1 ) system_cache ( 1 ) systemnavigator ( 1 ) tail recursion ( 1 ) tailrec ( 1 ) tap test ( 1 ) text ( 1 ) texteditingcontroller ( 1 ) textfield ( 1 ) texttheme ( 1 ) themedata ( 1 ) then ( 1 ) thread ( 1 ) throttle ( 1 ) time ( 1 ) tool ( 1 ) tools ( 1 ) tooltip ( 1 ) ts ( 1 ) tutorial ( 1 ) typescript ( 1 ) ui ( 1 ) unittest ( 1 ) update ( 1 ) usb ( 1 ) utf8 ( 1 ) ux ( 1 ) valuekey ( 1 ) variable ( 1 ) vector ( 1 ) versioncode ( 1 ) very_good ( 1 ) view ( 1 ) vim plugin ( 1 ) vimrc ( 1 ) virtualenv ( 1 ) wasm ( 1 ) web app ( 1 ) webview_flutter ( 1 ) while ( 1 ) widget tree ( 1 ) window ( 1 ) wsl ( 1 ) yield ( 1 ) 강의 ( 1 ) 개발 ( 1 ) 개발 공부 ( 1 ) 공부법 ( 1 ) 그래픽스 ( 1 ) 꼬리재귀 ( 1 ) 꿀팁 ( 1 ) 데노 ( 1 ) 두줄 ( 1 ) 디노 ( 1 ) 번역 ( 1 ) 블록 ( 1 ) 상태관리 ( 1 ) 실험 ( 1 ) 안드로이드 ( 1 ) 안드로이드프로젝트 ( 1 ) 안드로이드프로젝트복사 ( 1 ) 어이없는 ( 1 ) 조건부 임포트 ( 1 ) 주절주절분노조절실패의식으흐름 ( 1 ) 패키지 ( 1 ) 프로젝트복사 ( 1 ) 플러그인 ( 1 )