본문 바로가기

개발 노트/Kotlin

[Android] Activity Stack 및 backStack

각 앱마다 원하는 화면흐름이 있기 때문에 태스크 및 백스택 관리를 해야하는 경우가 발생한다

이번시간에는 이런 태스크 및 백스택 관리에 대해 정리해볼것이다

 

실행된 엑티비티들은 기본적으로 task라는 곳에 존재하게 된다

task사용자와 상호작용하는 엑티비티들을 묶어놓은 모음이다

예를 들어 이메일앱에는 새 메시지 목록을 표시하는 활동이 있을 수 있는데, 사용자가 메시지를 클릭하면 해당 메시지를 볼 수 있는 새 활동이 열린다. 그러면 이 새 활동은 백스택에 추가되고, 사용자가 뒤로탭하는 동작을 취하면 새 활동이 종료되고 스택에서 사라지는 걸 볼 수 있다. 

 

# 백스택이란?

실행된 엑티비티의 인스턴스들은 자료구조의 Stack구조로 저장되어 태스크에 속하게 되는데, 안드로이드 시스템에서는 이 스택을 Back Stack이라고 부른다

 

 

# 작업의 수명주기 및 작업의 백스택

스택은 데이터를 LIFO(후입선출) 방식으로 저장하고 관리하는 특징이 있다

보통 스택에 데이터를 넣는것을 push, 빼는것을 pop이라고 표현한다. 스택의 가장위에 있는 데이터는 Top이라고 표현한다

 

사용자가 백버튼을 누르면 스택의 탑에 있던 엑티비티 인스턴스되면서 백스택에서 제거가되고, 이전활동이 다시 시작된다

계속 백버튼을 눌러 모든 활동이 스택에서 삭제되면, 이 작업은 더이상 존재하지 않게된다

작업의 새로운 각 활동이 백 스택에 항목을 추가하는 방식을 나타낸다. 사용자가 뒤로를 탭하거나 뒤로 동작을 취하면 현재 활동이 소멸되고 이전 활동이 다시 시작된다

 

 

 

# 백그라운드 및 포그라운드 작업 

엑티비티2를 실행중인 상태에서 사용자가 홈키를 누르면 엑티비티2가 존재하는 태스크자체가 백그라운드 상태로 들어간다.

(이때, 태스크의 백스택에 저장되어있던 엑티비티들의 순서는 그대로 유지된채 백그라운드로 들어가게된다)

사용자가 다시 앱을 실행시키면 엑티비티2는 다시 포그라운드로 돌아오게되고 엑티비티2가 스택의 탑이 되면서 사용자에게 보이게 된다

 

태스크 B가 포그라운드에서 사용자 상호작용을 수신하는 동안 태스크 A는 백그라운드에서 재개를 기다리고 있다

  1. 사용자가 홈 버튼이나 동작을 사용한 다음 앱 런처에서 새 앱을 시작한다.
  2. 홈 화면이 표시되면 태스크A가 백그라운드로 전환됩니다. 새 앱이 시작되면 시스템은 자체 활동 스택과 함께 그 앱 (태스크 B)의 작업을 시작한다.
  3. 사용자는 앱과 상호작용한 후 다시 홈으로 돌아가 원래 태스크 A를 시작한 앱을 선택한다.
  4. 이제 태스크 A가 포그라운드로 나옵니다. 스택의 세 활동은 모두 그대로 유지되며 스택 맨 위의 활동이 다시 시작된다. 이 시점에서 사용자는 태스크 B로 다시 전환할 수도 있다. 홈으로 이동하여 해당 작업을 시작한 앱 아이콘을 선택하거나 최근 화면에서 앱의 작업을 선택하면 된다.

 

 

# 다중활동 인스턴스

단일 활동은 여러 번 인스턴스화할 수 있다

 

백 스택의 활동은 결코 재정렬되지 않으므로, 앱에서 사용자가 두 개 이상의 활동에서 특정 활동을 시작할 수 있도록 허용하는 경우 활동의 이전 인스턴스를 맨 위로 가져오는 것이 아니라,  활동의 새 인스턴스가 생성되어 스택으로 푸시된다. 따라서 앱의 한 활동은 그림처럼 다른 작업에서도 여러 번 인스턴스화될 수 있다

 

사용자가 뒤로 버튼이나 동작을 사용하여 뒤로 이동하면 활동 인스턴스는 열린 순서대로 표시되며, 각 인스턴스는 고유한 UI 상태를 갖습니다. 그러나 활동이 두 번 이상 인스턴스화되지 않도록 하려면 이 동작을 수정할 수 있다

 

 

# 멀티윈도우 환경

멀티윈도우 환경에서는 백그라운드와 포그라운드를 태스크 단위로 왔다갔다 자유롭게 이동할 수 있도록 지원한다

 

 

# 작업관리

아까 말한것처럼 일반적으로 후입선출 방식으로 태스크와 백스택을 관리한다. 이는 일반적으로 잘 작동해서 걱정할 필요는없지만, 정상적인 동작을 중단시켜야하는 경우가 생길수도있다. 예를들어 앱의 활동이 현재 작업 내에 배치되는 것이 아니라 시작할 때 새 작업을 시작하도록 해야할 수있다. 또는 활동을 시작할 때 백 스택 위에 새 인스턴스를 만드는 대신 활동의 기존 인스턴스를 가져오는 것이 좋다 . 또는 사용자가 작업을 떠날 때 루트 활동을 제외한 모든 활동에서 백 스택을 지우고 싶을 수도 있다.

이럴때 activity 메니페스트 요소의 속성startActivtiy()에 전달하는 인텐트 플래그를 사용하여 많은 작업을 할 수 있다

 

- 메니페스트 파일사용

매니페스트 파일에서 활동을 선언할 때 활동이 시작될 때 작업과 어떻게 연결되는지 지정할 수 있다

 

- 인텐트 플래그 사용

startActivity()를 호출할 때 새 활동이 현재 작업과 연결되는 방식 (또는 연결 여부)을 선언하는 플래그를 Intent에 포함할 수 있다

 

-> 두 활동이 모두 활동 B가 작업과 연결되는 방식을 정의하면 인텐트에 정의된 대로 활동 A의 요청이 매니페스트에 정의된 활동 B의 요청보다 우선 적용된다

 

 

 

# 매니페스트 파일을 사용하여 시작 모드 정의

런치모드는 AndroidManifest.xml 에서 설정 되도록이면 건들지 않는 것이 좋다 → 복잡한 부분이므로 꼬일 수 있다 → 안드로이드 공식 문서에서도 강조 하고 있다

 

- standard

  • 기본적으로 설정되어 있는 모드
  • 후입선출
  • 호출하는 모든 엑티비티가 위에 쌓인다
  • 엑티비티가 호출될때마다 태스크에 저장하기 때문에 여러개가 중복되서 저장될 수 있다

 

- singleTop

  • 가장 위(Top) 엑티비티는 중복해서 쌓이지 않는다
  • 가장 위 엑티비티가 아니라면 중복이 가능하다
  • top영역에 three Activity를 다시 Call 하면 기존 Activity를 재활용하여 호출 → onNewIntent()호출

 

 

- singleTask

  • 쌓여있던 스택은 남아있고, 새로운 스택공간이 하나 더 생긴다
  • 새로 생긴 스택 공간에 다른 엑티비티 스택이 쌓인다
  • 다중 인스턴스 생성이 안된다
  • 사용자가 보기엔 스탠다드와 똑같다

 

- singleInstance

  • 쌓여있던 스택은 남아있고, 새로운 스택공간이 하나 더 생긴다
  • 새로 생긴 스택 공간에는 다른 엑티비티 스택이 쌓이지 않는다
  • 다른 엑티비티가 호출되면 기존에 있던 스택공간에 쌓인다

 

 

#인텐트 플래그를 사용하여 시작 모드 정의

 

1. FLAG_ACTIVITY_NEW_TASK

singleTask와 동일한 동작을 한다

 

2. FLAG_ACTIVITY_SINGLE_TOP

singleTop과 동일한 동작을 한다

 

3. FLAG_ACTIVITY_CLEAR_TOP

새로 실행시키고자하는 엑티비티와 동일한 엑티비티가 현재 태스크 백스택에 이미 존재할 경우, 기존 엑티비티위에 쌓여있는 모든 인스턴스들을 제거한다. 이렇게하면 백스택의 탑에는 새로 실행시키고자하는 엑티비티와 동일한 기존 엑티비티가 남게되고, 이 엑티비티는 처음부터 재실행된다. 즉, 탑에 남은 엑티비티는 onCreate()메소드부터 다시 호출된다

FLAG_ACTIVITY_SINGLE_TOP과 함께 사용하면 탑에 남은 엑티비티는 onCreate()메소드가 아니라 onNewIntent()메소드가 호출된다

 

 

# 어피니티 처리

어피니티는 안드로이드 시스템이 태스크를 구분할 때 사용하는 태스크의 고유한 이름이다

activity요소의 taskAffinity 속성을 사용하여 활동의 어피니티를 수정할 수 있다

 

 

# 백 스택 삭제

사용자가 장시간 사용하지 않은 태스크가 있다면, 메모리 관리를 위해 해당 태스크의 백스택을 루트 엑티비티만 남기고 지워버린다.

하지만 엑티비티에 아래와 같은 속성들을 설정해주면, 시스템이 강제로 백스택을 비우는 동작을 제어할 수 있다

 

1. alwaysRetainTaskState

작업의 루트 활동에서 이 속성을 "true"로 설정하면 시스템은 이 태스크의 백스택을 비우지 않는다

예를 들어, 웹브라우저앱을 장시간 사용하지 않다가 갑작스럽게 사용했다고 쳐보자. 이때 오랜시간 방문하지 않았다는 이유로 기존에 띄워놓은 검색결과 등이 제거되어있다면 굉장히 당황스럽고 불편할 것이다. 이런경우, 이 속성이 유용하게 사용된다

 

2. clearTaskOnLaunch

작업의 루트 활동에서 이 속성을 "true"로 설정하면 사용자가 작업을 떠났다가 다시 돌아올 때마다 백스택을 루트 엑티비티만 남기고 모두 비운다. 즉, 돌아올때마다 기존에 쌓아두었던 엑티비티는 모두 제거되고, 첫 화면인 루트엑티비티가 보인다

 

3. finishOnTaskLaunch

"true"로 설정하면 활동은 현재 세션에서만 작업의 일부로 유지된다

사용자가 태스크을 떠났다가 다시 돌아오면 이 작업은 더 이상 존재하지 않는다

(사용자가 태스크을 떠났다가 다시 돌아오면 해당 엑티비티는 제거된다)

 

 

 

 

 

# 공식문서와 참고자료

https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#back-press-behavior

 

작업 및 백 스택  |  Android 개발자  |  Android Developers

작업은 사용자가 앱에서 어떤 작업을 하려고 할 때 상호작용하는 활동의 모음입니다. 이러한 활동은 스택(백 스택)에 각 활동이 열린 순서대로 정렬됩니다.

developer.android.com

https://heechokim.tistory.com/2

 

태스크 및 백 스택 이해하기

참고 자료 Android Developers (공식문서) - Tasks and back stack https://developer.android.com/guide/components/activities/tasks-and-back-stack Android Developers (공식 유튜브 채널) - Tasks and the Back Stack https://www.youtube.com/watch?v=Mv

heechokim.tistory.com

https://heechokim.tistory.com/5

 

태스크 및 백 스택 관리하기

참고 자료 Android Developers (공식 문서) - Tasks and the back stack https://developer.android.com/guide/components/activities/tasks-and-back-stack Android Developers Youtube (유튜브 채널) - Tasks and the Back Stack https://www.youtube.com/watc

heechokim.tistory.com