안드로이드/안드로이드 공부

[안드로이드] 활동 수명 주기 및 상태

요빈 2023. 3. 13. 21:36

활동 수명 주기 및 상태

활동 수명 주기(activity lifecycle)란 활동이 생성될 때부터 소멸되고 시스템이 리소스를 회수할 때까지의 전체 수명 동안 활동이 있을 수 있는 상태 집합을 말한다. 한마디로 활동의 전체 기간 중 일련의 액티비티 상태를 뜻한다.

사용자가 앱의 활동(앱 내부 및 외부) 사이를 탐색할 때 활동은 수명 주기에서 여러 상태로 전환된다.

아래 다이어그램은 모든 활동 수명 주기 상태를 보여준다.

 

활동 수명 주기 상태

 

Android 개발자는 활동 수명 주기를 파악해야 한다.활동이 수명 주기 상태 변경에 올바르게 응답하지 않으면 앱에 이상한 버그가 발생해 사용자가 동작을 혼동하거나,앱에서 Android 시스템 리소스를 너무 많이 사용할 수 있다.

 

활동 수명 주기의 각 단계에는 onCreate(), onStart(), onPause() 등과 같은 콜백 메서드가 있다.

액티비티가 생성, 시작, 중지 되는 등 상태가 변경되면 이와 연결된 콜백 메서드가 호출된다.

활동 클래스의 수명 주기 콜백 메서드를 재정의하면 사용자 또는 시스템 작업에 대한 응답으로 활동의 기본 동작을 변경할 수 있다.

아래 다이어그램에 재정의 가능한 콜백이 표시되어 있다.

 

Android 수명 주기에서 어떤 일이 일어나는지 파악하려면 다양한 수명 주기 메서드가 언제 호출되는지 알아야 한다.

 

1. onCreate()

 

onCreate() 메서드는 활동이 초기화된 직후(새 Activity 객체가 메모리에 만들어질 때) 한 번 호출된다. 

즉, onCreate()가 실행되면 활동이 생성되었다고 간주된다.

onCreate() 메서드를 호출하며 첫 초기화가 모두 이루어지고, 레이아웃을 확장하여 처음으로 레이아웃을 설정해 변수를 초기화한다.

* 앱 생성

 

2. onStart()

 

onStart() 메서드는 onCreate() 직후에 호출된다. onStart()가 실행되면 활동이 화면에 표시된다.

활동을 초기화하는 데 한 번만 호출되는 onCreate()와 달리 onStart()는 활동의 수명 주기에서 여러 번 호출될 수 있다.

onStart()는 상응하는 onStop() 수명 주기 메서드와 페어링되며, 앱 시작 후 해당 화면을 벗어나면 활동이 중지되고, 더 이상 화면에 표시되지 않는다. 

* 앱이 화면에 표시

 

3. onResume()

 

onResume() 메서드는 활동 포커스를 제공하고 사용자가 상호작용할 수 있도록 활동을 준비한다.

* 앱이 사용자 포커스 확보 -> 사용자가 앱과 상호작용할 수 있음

 

4. onDestroy()

 

onDestroy() 메서드는 활동이 완전히 종료되었을 때 실행되며 가비지 컬렉션이 될 수 있음을 의미한다.

가비지 컬렉션은 더 이상 사용하지 않을 객체의 자동 정리를 뜻한다.

onDestroy()가 호출되면 시스템은 이러한 리소스가 삭제될 수 있음을 인식하고 메모리 정리를 시작한다. 

활동은 finish() 메서드를 호출하거나 사용자가 앱을 강제 종료하는 경우 또는 앱이 오랫동안 화면에 표시되지 않으면 자체적으로 종료하는 경우가 있다.

 

여기서 요점은 onCreate()와 onDestroy()는 단일 활동 인스턴스의 전체 기간에 한번만 호출된다는 것이다.

onCreate()는 앱을 맨 처음 초기화할 때, onDestory()는 앱에서 사용하는 리소스를 정리할 때 호출된다.

 

5. onPause()

 

onPause()가 호출되면 앱에 더 이상 포커스가 없는 상태이다. 

* 앱이 포커스 상실

 

6. onStop()

 

onStop()이 호출되면 앱이 더 이상 화면에 표시되지 않는다.

활동은 중지되었지만 Activity 객체는 여전히 백그라운드 메모리에 있으며 소멸되지 않은 상태이다.

사용자가 앱으로 돌아올 수 있으므로 Android는 활동 리소스를 유지한다.

* 앱이 화면에 표시되지 않음

 

7. onRestart()

 

onRestart() 메서드는 onCreate()와 유사한 역할을 한다. 두 메서드 모두 활동이 표시되기 전에 호출된다.

onCreate() 메서드는 처음에만 호출되고 onRestart()는 그 후에 호출된다.

해당 메서드에는 활동이 처음으로 시작되지 않은 경우에만 호출하려는 코드가 배치된다.


수명 주기 사용 사례

1. Activity 열기 및 닫기

 

액티비티가 처음부터 시작되면 다음 세 가지 수명 주기 콜백이 모두 순서대로 호출된다.

- onCreate()
- onStart()
- onResume()

 

뒤로 버튼을 클릭해 실행중이던 앱을 종료하면 다음 세 수명 주기 콜백이 호출된다.

- onPause()
- onStop()
- onDestroy()

 

2. Activity 이동

 

앱을 사용하다 보면 앱 간의 전환, 또는 다른 액티비티(전화 통화와 같은)로 인한 중단이 발생하는 경우가 있다.

액티비티은 사용자가 액티비티에서 벗어날 때마다 완전히 닫히지 않는다.

 

액티비티이 화면에 더 이상 표시되지 않으면 이는 액티비티가 백그라운드에 배치되는 것이다.

이와 반대의 경우는 액티비티가 포그라운드에 있거나 화면에 표시되는 것이다.

앱은 백그라운드에 있을 때 시스템 리소스와 배터리 수명을 보존하기 위해 일반적으로 활발히 실행되지 않아야 한다. 

Activity 수명 주기와 콜백을 사용해 앱이 백그라운드로 이동하는 시점을 알 수 있어 진행중인 작업을 일시중지할 수 있다.

 

사용자가 앱으로 돌아오면 동일한 액티비티가 다시 시작되어 화면에 다시 표시된다.

수명 주기에서 이 부분을 앱의 표시 수명 주기라고 한다.

 

앱이 잠시 액티비티를 벗어났을 경우 다음 콜백이 순서대로 호출된다.

- onPause()
- onStop()

// 앱 재시작
- onRestart()
- onStart()
- onResume()

여기서 핵심은 onStart()와 onStop()은 사용자가 액티비티에서 나가거나 액티비티로 이동할 때 여러 번 호출된다는 점이다.

 

3. 부분적으로 Activity 숨기기

 

앱이 완전히 화면에 표시되고 사용자 포커스를 보유하는 수명 주기 부분을 대화형 수명 주기라고 한다.

포커스와 가시성의 차이가 중요한 이유는 액티비티가 화면에 부분적으로 표시되지만 사용자 포커스는 없을 수 있기 때문이다.

 

이런 경우에는 액티비티가 계속 부분적으로 표시되기 때문에 onStop()은 호출되지 않고,

사용자 포커스가 없어 사용자와 상호작용만 하지 못하는 것이기 때문에 onPause()만 호출된다.

onPause()만 사용한 중단은 보통 활동으로 돌아가거나 다른 액티비티 또는 앱으로 이동하기 전에 잠시 지속된다.

일반적으로 UI를 계속 업데이트하여 나머지 앱이 멈춘 것처럼 보이지 않도록 하는 것이 좋다.

액티비티가 포커스를 잃었을 때
- onPause()

액티비티가 포커스를 다시 얻었을 때
- onResume()

onResume()과 onPause()는 모두 포커스와 관련이 있습니다. 

onResume() 메서드는 액티비티에 포커스가 있을 때 호출되고 onPause()액티비티에 포커스가 없을 때 호출됩니다.


구성 변경

구성 변경은 대부분 사용자 상호작용으로 인해 발생한다. 예를 들어 사용자가 장치를 세로에서 가로로 회전하는 경우 새 방향에 맞게 레이아웃을 변경해야 하므로 장치 구성 변경에 따라 액티비티 상태도 변경될 수 있다.

 

기기나 에뮬레이터에서 활면이 회전되면 시스템은 모든 수명 주기 콜백을 호출해 액티비티를 종료한다.

그런 다음 액티비티가 다시 만들어 질 때 모든 수명 주기 콜백을 호출해 활동을 시작한다.

이러한 구성 변경이 발생하면 액티비티가 소멸되고 기본 상태로 다시 생성되며 사용자는 활동에 입력한 정보를 잃을 수 있다

따라서 사용자에게 혼란을 주지 않으려면 예기치 않은 데이터 손실을 방지하도록 앱을 개발하는 것이 중요하다.

 

구성 변경이 발생했을 때 화면의 데이터를 보존하는 방법은 다음과 같다.

 

  • ViewModel 사용
  • onSaveInstanceState()onRestoreInstanceState() 사용

ViewModel에 대해서는 따로 자세히 작성해두었다.

 

[안드로이드/Kotlin] ViewModel

ViewModel ViewModel은 뷰에 표시되는 앱 데이터 모델으로 UI 관련 데이터를 저장하고 관리해주는 역할을 한다. 생명주기에 영향을 많이 받는 UI 컨트롤러가 데이터에 관여하지 않도록 따로 분리한 것

yobinmoksw.tistory.com

 

해당 글에서는 두 번째 방식에 대해서만 다루고있다.

onSaveInstanceState() 메서드는 Activity가 소멸되면 필요할 수 있는 데이터를 저장하는 데 사용하는 콜백이다.

수명 주기 콜백에서 onSaveInstanceState()는 액티비티가 중지된 후(onStop)나 앱이 백그라운드로 전환될 때마다 호출된다.

 

 

액티비티의 상태는 액티비티 인스턴스 상태(InstanceState)라는 Bundle 객체에 키/값 쌍 세트로 저장된다.

키는 항상 문자열이며 Int 및 Boolean값과 같은 간단한 데이터를 번들에 넣을 수 있다.

시스템이 이 번들을 메모리에 유지하므로 번들의 데이터를 작게 유지하는 것이 좋다.

시스템은 액티비티가 중지되기 직전에 기본 상태 정보를 인스턴스 상태 번들에 저장하고 해당 번들을 새 액티비티 인스턴스로 전달하여 복원한다.

 

액티비티가 예기치 않게 파괴되고 재생성될 때 액티비티의  데이터 손실을 방지하려면 onSaveInstanceState() 메서드를 구현해야 한다.  액티비티가 소멸되고 다시 생성될 가능성이 있는 경우 시스템은 액티비티에서 onPause()와 onStop() 바로 다음에 이 메서드를 호출한다.

 

onSaveInstanceState() 메서드 사용 과정은 다음과 같다.

 

   - onSaveInstanceState() 메서드가 호출되면 저장할 데이터를 outState 매개변수에 넣는다.

     ex) outState.putInt("키", 값)

 

   - onCreate() 메서드가 호출되면 saveInstanceState값이 null인지 확인한다.

      1. null이 아닐 경우 savedInstanceState에 저장된 데이터를 사용한다.

          ex) savedInstanceState.getInt("키", 기본값)

      2. null일 경우 저장된 데이터가 없다는 의미로 별 다른 조치를 취할 필요가 없다.

 

인스턴스 상태에 저장하는 데이터는 현재 앱 세션 동안 이 특정 액티비티의 이 인스턴스에만 적용된다.

새 앱 세션을 중지했다가 다시 시작하면 액티비티 인스턴스 상태가 손실되고 액티비티가 기본 모양으로 되돌아간다.

앱 세션 간에 사용자 데이터를 저장해야 하는 경우 공유 기본 설정 또는 데이터베이스를 사용하는 것이 좋다.

 

액티비티가 재생성될 때 미리 저장해둔 액티비티 인스턴스 상태를 복원해야 한다.

상태 복원은  onCreate() 또는 onStart()가 호출된 후에  onRestoreInstanceState() 콜백을 사용하면 된다.

대부분의 경우, Activity 상태를 복원하는 더 좋은 위치는 UI를 가능한 한 빨리 사용하기 위해 onCreate()를 더 많이 사용한다.


** 장치를 세로에서 가로로 회전시키면 액티비티가 새로 생성되고 파괴되었다는 로그를 확인하였다.

하지만 EditText에 확인차 입력한 텍스트는 회전 시에도 유지된다는 것을 알 수 있었다.

이는 레이아웃에 있는 일부 뷰 요소의 상태정보가 구성변경 간에 자동으로 저장되기 때문이다.

 

* 아래 과정을 공부하며 작성한 글입니다.

https://developer.android.com/codelabs/basic-android-kotlin-training-activity-lifecycle?continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-kotlin-unit-3-pathway-1&hl=ko#0 

 

활동 수명 주기 단계  |  Android 개발자  |  Android Developers

이 Codelab에서는 활동 수명 주기와 로깅을 알아봅니다.

developer.android.com