[Android] Activity, Activity Stack(백 스택), Activity 수명 주기

junsuPark·2022년 11월 24일
0

Android

목록 보기
9/12
post-thumbnail

Activity

Activity ?

Activity란, 안드로이드 애플리케이션에서 UI 구성, 애플리케이션과 사용자 사이의 상호작용을 위한 가장 기본이 되는 컴포넌트입니다.

특징

모바일 애플리케이션의 시작점은 사용자의 의도에 따라서, 각기 다른 시점에서 비결정적론으로 시작될 수 있습니다. 예를 들어, 애플리케이션을 사용 중, 애플리케이션 내부의 공유 기능을 통해 Facebook의 '피드 작성'을 선택하면, Facebook 애플리케이션의 처음 메인 화면에서 애플리케이션을 시작하는 것이 아니라 '피드 작성' 화면에서부터 Facebook 애플리케이션을 시작합니다.

한 애플리케이션은 여러 Activity를 포함하고 있을 수 있으며, 한 화면에서는 하나의 Activity를 표시합니다.

안드로이드 애플리케이션의 처음 진입점은 Activity입니다. 프로그래밍 언어의 main() 함수처럼, manifest 파일에 작성된 Activity들 중에서 Intent Filter가 LAUNCHER 카테고리로 설정된 Activity가 앱 실행 시 가장 먼저 표시됩니다.


안드로이드 프레임워크의 Activity 인식

안드로이드 프레임워크에서 Activity를 인식시키기 위해서는, 즉 안드로이드 애플리케이션에서 Activity를 사용하기 위해서는, 프로젝트 파일 내부에 Activity 또는 AppCompatActivity 클래스를 상속받는 클래스가 존재한다면, manifest 파일에 해당 Activity에 대한 <activity> 태그를 추가해 주어야 하며, <activity> 태그의 name 속성에 해당 Activity 클래스의 위치를 명시해 주어야 합니다.

<manifest
    ...>

    <application
        ...>

        <activity
            ...
            android:name="${Class Location}"
            android:exported="true" />
				...
		</application>

</manifest>

이때, <activity> 태그 내부에 Activity의 이름을 나타내는 label, Activity의 UI 테마를 나타내는 theme 속성 등을 추가해 줄 수 있습니다.

<activity
    ...
    android:label="(Activity의 이름을 표시, String Resource를 주로 사용)"
    android:theme="(해당 Activity의 테마를 설정)"
    ... />

수명 주기

Activity 스택

Activty 스택 ?

안드로이드의 애플리케이션의 작업은 최소 하나의 Activity로 구성되어 있으며, Activity는 LIFO(Last In First Out) 구조인 스택 형식으로 관리됩니다. 이 스택을 스택을 안드로이드의 Activity 스택 또는 백 스택이라고 합니다. 스택 구조의 특성상 다시 정렬될 수 없으며, 특정한 Activity로의 전환이 까다롭습니다.

기존의 Activity에서 새로운 Activity를 시작하면 Activity 스택의 최상단에 쌓입니다. Activity 스택의 최상단에 있는 Activity만이 RESUMED 상태로 존재하며, 사용자와 상호작용할 수 있습니다.

사용자가 뒤로 버튼을 누르거나, 코드적으로 finish()를 호출하면, 해당 Activity를 스택에서 Pop 합니다. Activity 스택에 남아있는 Activity가 더는 없을 때 애플리케이션의 작업이 종료됩니다.

애플리케이션의 Activity 스택

애플리케이션의 Activity 스택이 비어있지 않은 상태에서 새로운 애플리케이션을 실행하면, 기존의 Activity 스택은 백그라운드에서 관리됩니다. 애플리케이션을 실행했을 때, 기존 애플리케이션의 Activity 스택이 존재한다면, 해당 스택에서 작업을 재개합니다.

하지만 시스템이 메모리 부족 등의 이유로 애플리케이션의 스택을 백그라운드에서 제거할 수 있습니다.


Activity의 상태

안드로이드의 Activity는 다음과 같은 상태들로 구분할 수 있습니다.

CREATED

Activity가 생성될 때 Activity의 상태입니다.

STARTED - Visible

Activity가 화면에 보이나, 상호작용이 가능하기 직전의 상태입니다. 따라서 사용자와 상호작용할 수 없습니다.

RESUMED - Visible

Activity가 화면에 보이고, 사용자와 상호작용이 가능한 상태입니다. Activity 스택의 최상단에 위치하고 있습니다.

PAUSED

Activity 스택에 다른 Activity가 쌓여 해당 Activity 일부가 가려지는 등, Activity의 포커스가 벗어난 상태입니다. 더는 사용자와 상호작용이 불가능합니다.

STOPPED

Activity 스택에 다른 Activity가 쌓여 Activity가 완전히 가려지는 상태입니다. Activity 스택에서 제거, 즉 소멸되지 않습니다.

DESTROYED

프로그래머가 직접, 또는 시스템이 Activity 스택에서 해당 Activity를 제거한 상태입니다. Activity가 소멸합니다.


Activity의 수명 주기 ?

모든 안드로이드 애플리케이션의 Activity는 각각의 수명주기를 가집니다. Activity는 수명주기에 따라 동작하며, 안드로이드 프레임워크는 각 수명주기에 대응하는 함수를 제공합니다. 프로그래머는 안드로이드 프레임워크에서 제공하는 함수를 Override 하여 Activity를 구성합니다.


수명 주기 콜백 함수

수명 주기 콜백 함수 ?

Activity의 수명 주기는 액티비티의 생성, 재개, 중단, 소멸 등 각각의 상태를 가지며, 안드로이드 프레임워크에서는 크게 6가지의 주요한 콜백 함수를 제공합니다. 또한 필요에 따라 수명 주기와 밀접한 연관이 있는 추가적인 콜백 함수를 구현할 수 있습니다.

  • onCreate()
  • onRestart()
  • onStart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroy()

시스템은 Activity의 수명 주기에 따라 자동으로 해당 Activity에 대한 수명 주기 콜백 함수를 호출합니다. 프로그래머가 직접 수명 주기 함수를 호출할 수 있으나, 권장되지 않는 방법입니다.

onCreate()

onCreate() 함수는 시스템이 Activity를 생성하면 가장 먼저 호출되는 메소드입니다. Activity의 생명주기 중 단 한 번만 실행되는 메서드이며, 화면에 표시하는 UI 초기화, 데이터 초기화 및 Activity와 ViewModel을 연동하는 작업 등등 Activity의 수명 주기 중 한 번만 실행되어야 하는 작업을 실행합니다.

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  
  ...
}

onCreate()가 호출될 시, Activity는 CREATED 상태를 가집니다. 또한, onCreate() 메소드가 수행된 이후 시스템은 계속해서 onStart(), onResume() 함수를 연달아 호출합니다.

savedInstanceState는 Activity의 onSaveInstanceState()메소드에서 저장된 Bundle 객체를 가지고 있습니다. 해당 Activity의 소멸되기 이전 상태의 데이터를 가지고 있으며, 화면 회전, 테마 변경 등의 Configuration Change 시 데이터를 보존하기 위해 사용합니다.

또한, LifeCycle과 연결된 컴포넌트에 ON_CREATE 이벤트를 수신합니다.


onRestart()

onRestart() 함수는 Activity가 STOPPED 상태에 있다가 다시 호출될 때 호출되는 함수입니다. onRestart() 함수가 호출된 이후에 onStart() 함수가 호출됩니다.

override fun onRestart() {
    super.onRestart()
  
    ...
}

onStart()

시스템에서 Activity의 onStart() 메서드가 호출하면 Activity는 STARTED 상태를 가집니다. Activity가 포어그라운드 화면에 표시된 직후 호출되는 메서드입니다. 사용자와 상호작용을 준비하며, 상호작용이 가능하기 직전에 호출되므로, 이 상태에서는 사용자와 상호작용 할 수 없습니다. 주로 애니메이션 발동 등 Activity에 진입할 때마다 실행되어야 하는 작업을 함수 내부에 구현합니다.

override fun onStart() {
    super.onStart()
  
    ...
}

Activity 스택에서 해당 Activity 위에 다른 Activity가 쌓여 있다가 위의 Activity가 제거될 때와 같이, 어떤 Activity가 중단된 후 다시 표시될 때 또한 onStart() 콜백 함수가 호출됩니다.

onCreate()와 마찬가지로, onStart() 함수가 호출되면 해당 함수에 머무르지 않습니다. onStart() 함수는 빠르게 종료되며, 시스템은 이어서 onResume() 콜백을 호출합니다.

LifeCycle과 연결된 컴포넌트에 ON_START 이벤트를 수신합니다.


onResume()

onResume() 함수는 Activity가 화면에 표시될 때 호출되며, 사용자가 상호작용할 수 있는 상태에 호출됩니다. 이때, RESUMED 상태를 가지게 됩니다. 주로 카메라 미리보기 등 사용자와 상호작용을 위한 로직을 내부에 구현합니다. 다른 Activity가 Activity 스택 위에 쌓이는 등 Activity에서 포커스를 떠날 때까지 RESUMED 상태를 유지하며, 해당 Activity에서 포커스를 떠난 경우 onPause()를 호출합니다. Activity가 다시 포커스를 받은 경우 onResume() 함수가 다시 호출됩니다.

override fun onResume() {
    super.onResume()
  
    ...
}

이때 LifeCycle과 연결된 컴포넌트에 ON_RESUME 이벤트를 수신합니다.


onPause()

onPause() 콜백 함수는 Activity 스택 위에 다른 Activity가 쌓여 더는 Activity가 보이지 않기 직전과 같이 해당 Activity가 화면에 더는 표시되지 않는 경우, 또는 전체 화면의 Permission 다이얼로그가 표시된 경우 등 Activity가 여전히 부분적으로 보이지만 포커스를 가지고 있지 않는 상태에 호출됩니다. 따라서 onPaused() 함수의 내부에서는 사용자의 상호작용이 불가능한 상태이며, Actiivity는 PAUSED 상태를 가집니다. 이 함수 내부에서는 GPS 등의 배터리에 영향을 끼칠 수 있는 리소스 할당을 해제하는 로직을 구현합니다.

override fun onPause() {
    super.onPause()
  
    ...
}

Activity가 소멸되지 않고 중단된 상태에서 다시 Activity를 재개할 경우 onResume() -> onPause() 순서로 호출됩니다. 따라서 onResume() 에서 실행한 로직을 구현하고, onPause() 에서 리소스 할당을 해제하는 것이 바람직합니다.

onPause() 함수는 다른 Activity가 호출되기 전에 호출되기 때문에 아주 잠시 동안 실행됩니다. 그러므로 onPause() 내부에서 애플리케이션 또는 사용자의 데이터를 저장하거나, 네트워크 호출을 하거나, 데이터베이스 트랜잭션 등의 기기의 리소스를 많이 사용하는 작업은 하지 않아야 합니다. 대신 onStop() 함수 내부에서 위 열거한 작업들을 구현합니다.

LifeCycle과 연결된 컴포넌트에 ON_PAUSE 이벤트를 수신합니다.


onStop()

onStop() 함수는 해당 Activity가 다른 Activity에 가려저 더는 화면에 표시되지 않을 때 호출되는 콜백입니다. 이 때 Activity는 STOPPED 상태를 가지며, 시스템은 해당 Activity의 실행이 완료되어 종료되는 시점에 onStop() 함수를 호출할 수 있습니다. onStop() 함수 내부에서는 애니메이션 중단, 정확한 위치 수집을 대략적인 위치 수집으로 변경하는 등 더이상 화면에서 표시되거나 구체적일 필요가 없는 구성요소를 해제하거나 조정해주는 로직을 구현합니다.

override fun onStop() {
    super.onStop()
  
    ...
}

onStop() 콜백이 호출된 Activity는 기기의 메모리에 저장되며, Activity가 다시 호출되면 onRestart() 콜백과 함께 저장된 메모리의 정보를 다시 호출합니다. 이때, 해당 Activity의 onResume() 함수 내부에서 구성된 View, EditText 등 위젯의 상태를 같이 저장하며, 프로그래머가 부가적으로 해당 상태를 저장하거나 복원할 필요가 없습니다.

앞서 잠시 언급했듯, onStop() 함수 내부에서는 기기의 리소스를 많이 사용하는 작업을 수행합니다.

Activity의 LifeCycle과 연관된 컴포넌트에 ON_STOP 이벤트를 수신합니다.


onDestroy()

onDestroy() 콜백 함수는 Activity가 소멸되기 직전에 호출됩니다. 이때, Activity에 관한 모든 정보가 메모리에서 할당 해제되며, Activity는 DESTROYED 상태를 가집니다. 프로그래머가 직접 finish() 함수를 호출하거나, 화면 방향 전환 및 기기 테마 변경 등의 애플리케이션의 Configuration Change가 발생할 때 onDestroy() 함수가 호출됩니다. 만약 Configuration Change가 발생하면, 화면의 구성이 변경된 후 Activity가 다시 표시되어야 하기 때문에 Activity의 onDestroy()가 호출된 즉시 새로운 Activity의 인스턴스를 만들고 onCreate() 함수를 호출하여 Activity를 다시 생성합니다.

override fun onDestroy() {
    super.onDestroy()
  
    ...
}

onDestroy() 메소드는 Thread 등 Activity와 연관된 리소스를 해제하는 함수입니다. 따라서 데이터를 저장하는 등의 작업을 수행해서는 안됩니다.

또한 LifeCycle과 연관된 컴포넌트에 ON_DESTROY 이벤트를 수신합니다.


참고 자료

Activity

Activity Lifecycle

0개의 댓글