[ActivityBackStack]
Task
-
특정 작업을 수행할 때 사용자와 상호작용하는 액티비티들의 모음
-
액티비티들은 실행된 순서대로 스택에 쌓인다. 이 스택을 백스택 이라고 한다.
- Example - 새 메시지의 목록을 보여주는 액티비티 하나를 가지는 이메일 앱
- 사용자가 메시지를 선택하면 해당 메시지를 보여주는 새 액티비티가 실행되고 백스택에 PUSH 된다.
- 사용자가 뒤로가기 버튼을 누르면 방금 열린 액티비티가 종료되고 스택에서 POP 된다.
- Example - 새 메시지의 목록을 보여주는 액티비티 하나를 가지는 이메일 앱
-
다중 창 지원 환경(7.0 이상) 에서 어플리케이션들이 동시에 실행될 때, 시스템이 각 창마다 task들을 분리하여 관리 한다. 각 창은 여러 태스크를 가질 수 있다. (Chromebooks 에서 실행되는 안드로이드 앱의 경우도 마찬가지이다)
-
기기의 홈 화면은 대부분의 Task 들이 시작되는 곳이다. 사용자가 앱 런처에서 아이콘을 터치하면 해당 앱의 Task 가 Foreground 로 온다. 만약 앱의 Task가 이미 존재하지 않는다면, 새로운 Task 가 생성되고 해당 앱의 main activity 가 새로운 스택의 root activity 가 된다.
Back Stack Process
- 현재 액티비티가 또 다른 액티비티를 실행할 때, 새로 실행된 액티비티는 스택의 top에 PUSH 되고 집중 받는다.
- 이전의 액티비티는 스택에 유지되지만 실행이 멈춰진다.(Stop) 이 때, 시스템은 멈춰진 액티비티의 현재 UI 상태를 저장해둔다.
- 유저가 Back 버튼을 누르면 현재 액티비티는 스택의 top 에서 POP 된다.(Destroy) 그리고 직전의 액티비티가 멈출 때 저장한 UI 상태를 불러와서 다시 실행된다.(Resume)
- 스택에 있는 액티비티들은 절대 재배열 되지 않는다. 오직 스택에서 PUSH, POP 만 발생한다.
Background, Foreground
- Cohesive Task
- 사용자가 새 Task를 시작하거나 홈 버튼을 통해 홈 화면으로 갈 때 Task는 백그라운드로 이동 한다.
- 백그라운드에 있는 동안 Task 내 모든 액티비티들은 BackStack 을 유지한채 멈춘다.
Example - Task A 의 백스택에 세 개의 액티비티가 있다. 1. 사용자가 홈버튼을 누르고 앱 런처에서 새 앱을 실행시킨다. 홈 버튼으로 인해 홈화면이 나타날 때, Task A 는 백그라운드로 이동한다. 2. 새 앱이 실행되면 시스템은 해당 앱을 위한 Task B를 생성하고 해당 앱의 액티비티들을 스택에 쌓는다. 3. 사용자가 새 앱을 어느정도 사용하다가 홈 버튼을 누르고 기존에 생성했던 Task A 를 위한 앱을 다시 실행시킨다. Task A 는 다시 포그라운드로 이동되며 이전에 사용했던 그대로 다시 실행된다. 4. 이 시점에서 사용자는 홈으로 이동하여 해당 작업을 시작한 앱 아이콘을 선택하거나 최근 화면에서 앱의 작업을 선택하여 작업 B로 다시 전환 할 수 있다. (Android MultiTasking)
Note : 백그라운드에는 여러 개의 Task 가 존재 할 수 있다. 하지만 동시에 많은 백그라운드 태스크를 실행시키면, 시스템은 메모리를 복구하기 위해 백그라운드 액티비티들을 파괴하기 시작한다.
Activity 와 Task 의 기본 동작
- 백스택에 있는 액티비티들은 절대 재배열 되지 않는다. 만약 사용자가 앱을 실행하여 여러 액티비티 중 특정 액티비티를 실행시키게 되면, 지정된 액티비티의 인스턴스가 새로이 생성되고 스택으로 PUSH 된다 (해당 액티비티의 이전 인스턴스를 TOP 으로 가져오기 보다는).
- 따라서 위 그림에서 볼 수 있듯이, 앱에 존재하는 하나의 액티비티는 여러번 인스턴스화 될 수 있다 (심지어 다른 Task 상에서).
- 만약 사용자가 Back 버튼을 사용하여 뒤로 탐색한다면, 실행됐던 순서대로 액티비티의 인스턴스가 드러나게 된다.
- 우리가 원한다면 이러한 동작들을 액티비티가 한 번만 인스턴스 되도록 바꿀 수 있다. 이 점은 뒤에서 쓰여질 Task 관리 에서 다뤄진다.
- Activity 와 Task 의 기본 동작을 요약하면 다음과 같다.
- Activiy A 가 Activity B 를 실행시킬 때, Activity A 는 Stop 된다. 하지만 시스템은 Activity A 의 현 상태(스크롤 위치, 입력된 텍스트 등등) 를 유지 한다. 만약 사용자가 Activity B 를 사용하다가 Back 버튼을 누르면, Activity A 는 Resume 되고 유지된 상태가 복구된다.
- 사용자가 Home 버튼을 눌러서 Task 를 떠나게 되면, 당시 Activity 는 Stop 되고 Task 는 Background 로 옮겨진다. 시스템은 해당 Task 의 모든 Activity 상태를 유지 한다. 이후에 사용자가 해당 Task 를 불러오는 앱을 실행시키면 Task 는 Foreground 로 돌아오고 스택의 TOP 에 있는 Activity 는 Resume 된다.
Task 관리
- 위에서 설명했던 Task 의 기본 동작을 원하는 대로 바꿀 수 있다.
-
< activity > manifest 성분의 attribute
- taskAffinity
- launchMode
- allowTaskReparenting
- clearTaskOnLaunch
- alwaysRetainTaskState
- finishOnTaskLaunch
-
startActivity()
를 이용한 intent 의 flag- FLAG_ACTIVITY_NEW_TASK
- FLAG_ACTIVITY_CLEAR_TOP
- FLAG_ACTIVITY_SINGLE_TOP
-
Caution : 대부분의 앱이 Activity 와 Task 의 기본 동작을 방해하면 안된다. 만약 특정 Activity 가 기본 동작을 수정 하도록 만들고 싶다면, 주의를 기울여서 실행 시킬 때나 다른 Activity 나 Task 에서 뒤로 돌아갈 때 특정 Activity 가 잘 동작하는지 확실히 테스트 해야 한다.
Launch Mode
- Launch Mode 는 개발자가 Activity 의 새 인스턴스를 Task 와 어떻게 결합시킬 지 정의하는 속성이다.
- Launch Mode 를 설정하는 방법은 두 가지 가 있다.
- manifest file
- manifest file 에서 activity 를 선언 할 때, 해당 activity 가 시작될 때 Task 에 결합되는 방식을 지정할 수 있다.
- Intent flags
startActivity()
메서드를 호출 할 때,Intent
안에 flag 값을 설정하여 Activity 의 Launch Mode 를 설정 할 수 있다.
- manifest file
Note : manifest 파일에서 사용 가능한 일부 Launch Mode 는 Intent 의 flag 로 사용 할 수 없다. 반대로 flag 로써 사용 가능한 일부 Launch Mode 가 manifest 파일에서 선언 될 수 없다.
Manifest file
- manifest file 에서 Activity 를 선언 할 때,
<activity>
의launchMode
사용하여 Activity 가 Task 와 결합되는 방식을 지정할 수 있다. launchMode
속성에는 총 4가지 속성이 존재한다. ( 추가 내용 : https://choboit.tistory.com/24 )- standard
- Default 값
- Activity 가 실행될 때마다 새 인스턴스 를 생성한다.
- singleTop
- 실행시킨 Activity 의 인스턴스가 현재 Task 의 TOP 에 이미 존재할 경우,
onNewIntent()
메서드를 통해 기존의 Activity 로 intent 를 라우팅한다.
- 실행시킨 Activity 의 인스턴스가 현재 Task 의 TOP 에 이미 존재할 경우,
- singleTask
- 새로운 Task 를 생성하고 새 Task 에서 root Activity 로 인스턴스화 한다.
- 하지만 다른 Task 에서 해당 Activity 가 이미 존재 한다면
onNewIntent()
메서드를 통해 기존의 Activity 로 intent 를 라우팅한다. - 각 Activity 의 인스턴스는 한 번에 한 개만 존재 할 수 있다.
- singleInstance
- 하나의 Task 에는 오직 하나의 Activity 인스턴스만 존재한다.
- standard
Scenario : singleTask 로 launchMode 가 설정된 브라우저 앱 1. 안드로이드 브라우저 앱은 웹 브라우저 Activity 가 항상 자체 Task 에서 열리도록 선언한다(
<activity>
요소에 singleTask launch mode 로 설정함). 2. 사용자의 앱이 안드로이드 브라우저를 열기 위해 intent 를 발생시키면, 해당 액티비티는 사용자 앱의 Task 내에 위치하지 않는다. 3. 브라우저를 위한 새 Task 를 만들거나 만약 이미 background 에 존재한다면 기존의 Task 를 foreground 로 가져오고 새 intent 값을 전달한다. 4. Back 버튼은 항상 사용자에게 이전의 Activity 를 보여주게 한다. 그런데 만약 singleTask 로 설정한 Activity 를 시작했을 때 해당 Activity 가 background 에 이미 존재하다면 해당 Activity 가 포함되어 있는 Task 통째로 foreground 로 가져와진다. 5. 이 때 백스택은 방금 가져온 Task 의 모든 Activity 를 백스택의 TOP 에 포함시킨다.
- manifest 에서 설정하는 launchMode 사용에 관련된 더 많은 정보를 얻고 싶다면, <activity> 문서를 참고한다. 해당 문서에는
launchMode
속성과 허용 가능한 값들이 더 자세히 나타나있다.
Intent flags
- startActivity() 로 전달되는 Intent 의 flag 값을 통해 Activity 가 Task 와 결합되는 기본 방식을 변경 할 수 있다.
- flag 값은 총 3 가지가 존재하다.
- FLAG_ACTIVITY_NEW_TASK
- singleTask 와 같이 동작한다.
- 새 Task 에 Activity 를 시작한다. 만약 Task 가 이미 존재한다면 Task 는 이전의 상태를 복구하여 foreground 로 돌아오고 해당 Activity 는
onNewIntent()
메서드로 새 Intent 값을 받는다.
- FLAG_ACTIVITY_SINGLE_TOP
- singleTop 과 같이 동작한다.
- 실행되려는 Activity 가 현재 동작중인 Activity 일 때(백스택의 TOP 에 존재),
onNewIntent()
메서드를 통해 Intent 값을 받는다.
- FLAG_ACTIVITY_CLEAR_TOP
- 현재 Task 에서 이미 실행 중인 Activity 를 실행시킬 때, 해당 Activity 의 새 Instance 를 생성하지 않고 Task 내에 TOP 에 존재하는 다른 Activity 들을 모두 제거 한다. 그리고 전달하려는 Intent 값은
onNewIntent()
메서드를 통해 Resume 된 해당 Activity(TOP에 위치) 로 전달된다. - FLAG_ACTIVITY_CLEAR_TOP 은 FLAG_ACTIVITY_NEW_TASK 와 결합하여 자주 사용 된다. 함께 쓰면 다른 Task 에서 이미 존재하는 Activity 를 Intent 값에 반응 할 수 있는 위치로 옮길 수 있다.
- 현재 Task 에서 이미 실행 중인 Activity 를 실행시킬 때, 해당 Activity 의 새 Instance 를 생성하지 않고 Task 내에 TOP 에 존재하는 다른 Activity 들을 모두 제거 한다. 그리고 전달하려는 Intent 값은
- FLAG_ACTIVITY_NEW_TASK
참고자료 (출처)
https://codechacha.com/ko/activity-backstack/
https://developer.android.com/guide/components/activities/tasks-and-back-stack
'Android Developer' 카테고리의 다른 글
[Android] APK 용량 줄이기 (0) | 2019.10.08 |
---|---|
[Android] AsyncTask (0) | 2019.08.02 |
[Android] Log (0) | 2019.07.10 |
[Android] Activity의 LaunchMode (0) | 2019.07.10 |
[Android] 난독화(Proguard) (0) | 2019.05.14 |