1. 요약
2. Task
2-1. 개념
2-2. Task 제어의 필요성
3. AndroidManifest에서의 제어
4. 소스 코드로 제어
5. 추가로 나올 수 있는 질문
5-1. 기존의 activity를 재사용하는 경우, 처음 진입하는 상황인지 다시 진입하는 상황인지 어떻게 구분하죠?
1. 요약
🧑💻: Activity Intent Flag에 대해 설명해 보세요.
👨🏻🦱: Activity의 중복 문제나 흐름을 제어하고 싶을 때 Intent Flag를 사용합니다.
AndroidManifest에서 액티비티 태그 안에 flag를 설정하거나
소스 코드에서 intent에 addflag를 사용하여 제어할 수 있습니다.
+) 좀 더 구체적인 상황을 주고 사용해야 할 flag를 물어보기도 하고
flag 몇 개 예시로 들어달라고 하기도 한다.
2. Task
2-1. 개념
- 관련된 실행 액티비티들을 순서대로 묶어 관리하는 것
- ex) 은행 뱅킹 앱을 사용할 때 로그인 - 계좌조회 - 계좌이체 순으로 실행된 액티비티들을 묶어 관리한다.
- 서로 다른 패키지의 액티비티가 실행되더라도 하나의 실행 흐름 안에 있게 됨
- ex) 유튜브 보다가 링크 타고 인터넷으로 넘어갔다가 카톡 와서 카톡으로 넘어갔다가...
- 사용자 입장에서는 이것도 하나의 패키지라고 생각할 수도 있음
- Stack 형태로 액티비티들이 차곡차곡 쌓이는 구조
- 가장 밑에 깔려있는 액티비티를 root activity라고 부름
- 가장 위에 있는 액티비티를 top activity라고 부름
- top activity를 제외한 나머지 액티비티들은 onStop 상태가 됨
- 뒤로 가기를 하면 다음 액티비티가 top activity가 됨
우리가 아는 이 최근 실행 앱 목록이 바로 Task의 목록이다.
각 Task에는 top activity들이 표시된다.
2-2. Task 제어의 필요성
반복되는 activity 또는 중복 실행 방지를 위해 필요하다.
예를 들어 뱅킹 앱을 쓸 때
홈 - 계좌조회 - 계좌이체 - 이체완료 - 계좌조회 순서로 액티비티를 실행했을 때
만약 뒤로가기를 누른다면 이체완료 페이지로 가는 게 맞을까 아니면 홈으로 가는 게 맞을까?
계좌조회가 중복되는 상황에서 새로운 액티비티를 보여주는 게 맞을까 아니면 이전 액티비티를 재사용하는 게 맞을까?
이런 고민들로부터 Task 제어의 필요성이 시작된다.
3. AndroidManifest 에서 제어
<activity android:launchMode="singleTask"/>
Task를 제어하는 방법은 2가지가 있는데
[목차 3]에서 설명할 방법은 AndroidManifest에서 설정하는 방법이다.
매니페스트에 등록할 때는 activity 태그 안에 android:launchMode="singleTask" 이런 식으로 설정해주면 된다.
여기서 사용할 수 있는 실행 모드의 종류는 다음과 같다.
3-1. standard
standard는 activity를 실행하는 순서대로 그냥 스택에 쌓는 실행 모드이다.
task 내에 중복된 activity 허용하며
따로 실행 모드를 설정하지 않으면 기본으로 설정되는 값이기도 하다.
3-2. singleTop
top activity와 동일한 activity 실행 시 stack에 쌓지 않고 기존의 top activity 재사용하는 실행모드이다.
이름에서 알 수 있듯이 top에 있는 activity는 single이어야 한다.
위 사진에서 좌측처럼 top에 똑같은 activity가 2개 이상 연달아 있을 수 없다.
3-3. singleTask
singleTask 모드인 activity는 무조건 root activity여야 한다.
만약 다른 activity가 root activity로 있다면 새로운 Task를 만든다. 그리고 거기에 activity를 넣는다.
위 예시는 Task 1의 root activity가 A이기 때문에 C를 호출하면 새로운 Task를 만들어버리고 거기에 C를 넣는 모습이다.
또, singleTask는 중복을 허용하지 않으며 activity를 재사용한다.
그리고 재사용할 activity보다 위에 있는 activity들은 전부 stack에서 지워버린다. (onDestroy 됨)
위 예시에서는 A를 재사용하면서 위에 있던 B와 C를 날려버리는 모습이다.
3-4. singleInstance
하나의 task에 하나의 activity가 존재하는 실행 모드이다.
root activity 로만 존재한다. (= root activity가 곧 top activity)
지금까지 AndroidManifest에서 설정 가능한 실행 모드들을 알아보았다.
소스 코드로도 flag 값을 주어 task를 제어할 수 있는데 그 종류가 좀 더 다양하다.
[목차 4]에서 이어서 알아보자.
4. 소스 코드로 제어
val intent = Intent(this, AccountActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
startActivity(intent)
소스 코드로 Task를 제어하고 싶다면 intent에 addFlags로 값을 넣어주면 된다.
이때 들어갈 수 있는 Flag값의 종류는 무려 20가지가 넘는다.
이 포스팅 안에 다 설명하기는 무리이므로... 자세한 내용은 공식문서를 참고하고
자주 사용되는 대표적인 flag만 알아보도록 하자.
- FLAG_ACTIVITY_CLEAR_TOP
- 호출하려는 액티비티가 스택에 존재하면, 해당 액티비티를 최상위로 올리면서 그 위에 존재하던 액티비티를 전부 삭제한다.
- FLAG_ACTIVITY_SINGLE_TOP
- top activity와 동일한 activity 실행 시, 해당 activity를 다시 생성하지 않고 기존의 top activity 재사용
- FLAG_ACTIVITY_NO_HISTORY
- activitiy가 스택에 쌓이지 않도록 한다. Splash Screen 등에 사용됨
아직 액티비티끼리의 관계가 복잡한 프로젝트를 진행해보지 않아서 그런지 몰라도
개인적으로 거의 이 3가지 Flag 값만 사용해왔던 것 같다.
val intent = Intent(this, AccountActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
그리고 원하다면 이렇게 flag를 조합해서 사용할 수도 있다.
5. 추가로 나올 수 있는 질문
5-1. 기존의 activity를 재사용하는 경우, 처음 진입하는 상황인지 다시 진입하는 상황인지 어떻게 구분하죠?
singleTop이나 singleTask를 통해 기존의 activity를 재사용하게 되는 경우
onPause와 onResume만 뜨게 되므로 이게 액티비티에 처음 진입하는 상황인지 다시 진입하는 상황인지 알 수가 없다.
(새로 진입하는 상황에서도 onResume이 뜨니까!)
이때, onNewIntent라는 메서드를 오버라이딩하면 그걸 구분할 수 있다.
즉, 다시 진입하는 경우 onCreate대신 onNewIntent가 호출되고 onResume이 호출되므로
onNewIntent로 구분할 수 있다.
💡 느낀 점
- 개인적으로 종류가 무엇이 있냐고 물어보는 건 조금 치사한 질문이라고 생각했는데 (기억력 테스트 같아서...) 내가 면접 경험이 많지 않음에도 무려 3군데의 회사에서 이 질문이 나왔다. 음... 외워둘 필요가 있을 것 같다.
- Activity보다는 Fragment로 화면 구성을 하는 편이라 사실 나는 Intent Flag를 쓸 일이 거의 없었다. 현업에서는 어떤 방식을 사용할지 너무 궁금하다. 빨리 취업시켜주세요...
📘참고한 자료
- Tasks and the back stack - 안드로이드 공식문서
- Activity의 LaunchMode - ChobolT님 블로그
- 그림으로 이해하는 Activity LaunchMode 실험 - yebon님 블로그ㅇㅇ
- 안드로이드 Intent Flag 정리 - p4stel-dev.log
'오늘은 뭘 배울까? > Android' 카테고리의 다른 글
Delegation이 무엇인지 아시나요? (상속과 구성까지 알아보자) (4) | 2022.07.11 |
---|---|
Observable Field와 LiveData의 차이가 무엇인가요? (0) | 2022.07.09 |
lateinit과 by lazy의 차이가 무엇인가요? (8) | 2022.06.22 |
addToBackStack에 대한 고찰 (16) | 2021.10.06 |
startActivityForResult는 왜 deprecated 되었는가? (4) | 2021.09.28 |
댓글