The activity lifecycle

노준혁·2023년 2월 15일
0

https://developer.android.com/guide/components/activities/activity-lifecycle#oncreate


  • The activity lifecycle

    • 사용자가 앱을 탐색하고, 앱에서 나가고, 앱으로 다시 돌아가면, 앱의 Activity 인스턴스는 lifecycle 안에서 다른 states들로 전환됨.
    • Activity Class는 Activity가 state의 변화(시스템이 Activity을 생성, 중단 또는 다시 시작하거나, Activity가 있는 프로세스를 종료(destroy)하는 등)를 감지할 수 있는 여러 콜백을 제공
    • 사용자가 Activity을 벗어났다가 다시 돌아왔을 때 Activity가 동작하는 방식을 lifecylce의 callback methods에서 선언할 수 있음.
      ex) 스트리밍 동영상 플레이어를 빌드하는 경우를 생각해보자.
      사용자가 스트리밍 동영상 플레이어가 아닌 다른 앱으로 전환할 때 동영상을 일시중지하고 네트워크 연결을 종료할 수 있다. 그 후 사용자가 다시 동영상 플레이어로 돌아오면 네트워크를 다시 연결하고, 사용자가 일시중지한 지점에서 동영상을 다시 시작하도록 할 수 있다.
      즉, 각 콜백은 state가 변화하는 시점마다 적합한 특정 작업을 실행할 수 있게 만들 수 있다.
      이처럼 적시에 알맞은 작업을 하고 적절하게 state 전환을 처리하면 앱이 더욱 안정적으로 기능할 수 있다.

  • good implementation of the lifecycle callback을 통해 방지할 수 있는 문제
    • 사용자가 앱을 사용하는 도중에 전화가 걸려오거나 다른 앱으로 전환할 때 비정상 종료되는 문제
    • 사용자가 앱을 지속적으로 사용하지 않는 경우 시스템 리소스가 소비되는 문제
    • 사용자가 앱에서 나갔다가 나중에 돌아왔을 때 사용자의 진행 상태가 저장되지 않는 문제
    • 화면이 가로 방향과 세로 방향 간에 회전할 경우, 비정상 종료되거나 사용자의 진행 상태가 저장되지 않는 문제

  • Activity-lifecycle concepts

  • activity lifecycle의 stages 간에 전환하기 위해 Activity Class는 6가지 콜백으로 구성된 core set의 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()를 제공한다. Activity가 새로운 state에 들어가면 시스템은 각 콜백을 호출하게 되는 구조.

  • 사용자가 Activity을 벗어나기 시작하면 시스템은 Activity를 해체할 메서드를 호출한다. 어떤 경우에는 부분적으로만 해체하기도 하는데, 이때 Activity는 여전히 메모리 안에 남아 있으며(예: 사용자가 다른 앱으로 전환할 경우) foreground로 다시 돌아올 수 있다. 사용자가 해당 Activity로 돌아오는 경우 사용자가 종료한 지점에서 Activity가 다시 시작된다. 단, 몇 가지 예외를 제외하고 앱은 백그라운드에서 실행될 때 Activity를 실행할 수 없다.

  • Activity의 복잡도에 따라, 모든 lifecycle methods들을 구현할 필요가 없을수도 있지만,각각의 lifecycle methods들을 이해하고, 사용자가 예상한 대로 앱이 동작하도록 필요한 lifecycle methods들을 구현하는 것이 중요!


  • Lifecycle callbacks

setContentView()를 호출하는 것과 같은 일부 작업은 Activity lifecycle method 그 자체에 속해 있다. 그러나 종속적인 component의 작업을 구현하는 코드는 해당 component 안에 넣어야 한다. 이를 위해서는 종속적인 component가 lifecycle를 인식하도록 해야 한다.

  • onCreate()
    이 콜백은 시스템이 먼저 Activity를 생성할 때 실행되는 것으로, 필수적으로 구현해야 한다.
    Activity가 생성되면 Activity는 Created state가 된다. onCreate() method에서 Activity의 전체 lifecycle 동안 한 번만 일어나야 하는 기본 애플리케이션 startup logic을 실행한다.
    onCreate() method는 사용자 인터페이스 선언(XML 레이아웃 파일에 정의됨), 멤버 변수 정의, 일부 UI 구성 등의 Activity에 관한 fundamental한 setup을 진행한다.

Activity는 Created state에 쭉 머무르지 않고, onCreate() 메서드가 실행을 완료하면 Started state가 되고, 시스템이 연달아 onStart()와 onResume() 메서드를 호출하게 된다.

  • onStart()
    Activity가 Started state에 들어가면 시스템은 이 콜백을 호출한다. onStart()가 호출되면 Activity가 사용자에게 표시되고, 앱은 Activity를 foreground에 보내 상호작용할 수 있도록 준비한다.
    보통 onStart()에서 앱이 UI를 관리하는 코드를 초기화함.

활동이 Started state로 전환하면 이 Activity의 lifecylce과 연결된 모든 lifecycle 인식 component는 ON_START 이벤트를 수신하게 됨.

onStart() method가 완료되면 Activity가 Resumed state에 들어가고, 시스템이 onResume() 메서드를 호출함.

  • onResume()
    Activity가 Resumed state에 들어가면 foreground에 표시되고 시스템이 onResume() 콜백을 호출한다.
    이 state에서부터 앱이 사용자와 상호작용을 하는데, 어떤 이벤트가 발생하여 앱에서 포커스가 떠날 때까지 앱이 Resumed state에 머무른다.
    ex) 전화가 오거나, 사용자가 다른 Activity로 이동하거나, 기기 화면이 꺼지는 이벤트가 발생하면 앱에서 포커스가 떠나게 됨.

Activity가 Resumed state로 전환되면 이 Activity의 lifecycle과 연결된 모든 lifecycle 인식 component(=lifecycle-aware component)는 ON_RESUME 이벤트를 수신한다. 이 Resumend state에서 lifecycle component가 foreground에서 사용자에게 보이는 동안 실행해야 하는 모든 기능을 활성화할 수 있음(ex. 카메라 미리보기 시작)

이때부터 만약, interruptive한 이벤트가 발생하면 Activity는 Paused state에 들어가고, 시스템이 onPause() 콜백을 호출한다.

Activity가 Paused state에서 Resumed state로 돌아오면 시스템이 onResume() 메서드를 다시 한번 호출한다. 그렇기에 반드시 onResume()을 구현할 때, onPause() 동안 해제되는 Component를 초기화하고, Activity가 Resumed state로 전환될 때마다 필요한 다른 초기화 작업도 수행해야 한다.

  • onPause()
    시스템은 사용자가 Acitivity를 떠나는 것을 나타내는 첫 번째 신호로 이 메서드를 호출한다(하지만 해당 Acitivity가 항상 destroy되는 것은 아님). Acitivity가 foreground에 있지 않게 되었다는 것을 나타내는 것이다. onPause() 메서드를 사용하여 Activity가 Paused state가 되었을 때 operations이 계속 실행되어서는 안 된다.
    또한, onPause()는 아주 잠깐 실행되므로 데이터를 save하는 operation을 실행하기에는 시간이 부족하다. 따라서 onPause()를 사용하여 애플리케이션 또는 사용자 데이터를 저장하거나, 네트워크 호출을 하거나, 데이터베이스 트랜잭션을 실행해서는 안된다.
    그 대신, 부하가 큰 종료 작업은 onStop() 상태일 때 실행하면 된다.

Activity가 Paused state에서 Resumed state로 돌아온다면 시스템은 Activity 인스턴스를 메모리에 남겨두고, 시스템이 onResume()을 호출할 때 이 인스턴스를 다시 호출하는 구조이다. Activity가 완전히 invisible되면 시스템은 onStop()을 호출.

  • onStop()
    Activity가 사용자에게 더 이상 표시되지 않으면 Stopped state에 들어가고, 시스템은 onStop() 콜백을 호출한다.

Activity가 Stopped state로 전환하면 이 Activity의 lifecycle과 연결된 모든 lifecycle-aware component는 ON_STOP 이벤트를 수신한다.

onStop() 메서드에서는 앱이 사용자에게 보이지 않는 동안, 앱이 필요로 하지 않는 리소스를 해제하거나 조정해야 한다.
또한 onStop()을 사용하여 CPU를 비교적 많이 소모하는 종료 작업을 실행해야 한다.
ex) 데이터를 데이터베이스에 저장할 적절한 시기를 찾지 못했다면 onStop() 상태일 때 저장하면 됨.

Activity가 Stopped state에 들어가면 Activity 객체는 메모리 안에 머무르게 되고 Activity가 다시 시작되면 다시 호출된다.

Activity는 Stopped state에서 다시 시작되어 사용자와 상호작용하거나, 실행을 종료하고 사라지는 로직에서, Activity가 다시 시작되는 부분은 시스템은이 onRestart()를 호출하게 된다. Activity가 실행을 종료하면 시스템은 onDestroy()를 호출한다.

  • onDestroy()
    onDestroy()는 Activity가 destroy되기 전에 호출된다.

시스템은 다음 중 하나에 해당할 때 이 콜백을 호출함.

  1. (사용자가 Activity를 완전히 끄거나 Activity에서 finish()가 호출되어) Activity가 종료되는 경우
  2. 구성 변경(예: 기기 회전 또는 멀티 윈도우 모드)으로 인해 시스템이 일시적으로 Activity를 destroy 시키는 경우

Activity가 destroyed state로 전환하면 이 Activity의 lifecycle과 연결된 모든 lifecycle-aware component는 ON_DESTROY 이벤트를 수신한다. 여기서 lifecycle component는 Activity가 destroy되기 전에 필요한 것들을 clean up하는 과정을 거칠 수 있다.

Activity가 종료되는 경우, onDestroy()는 Activity가 수신하는 마지막 lifecycle 콜백이이다. 따라서, onDestroy() 콜백은 이전의 콜백에서 아직 해제되지 않은 모든 리소스(예: onStop())를 해제해야 합니다.

구성 변경으로 인해 onDestroy()가 호출되는 경우 시스템이 즉시 새 Activity 인스턴스를 생성한 다음, 새로운 구성에서 그 새로운 인스턴스에 관해 onCreate()를 호출하게 된다.


  • Navigating between activities
    앱은 lifecycle 동안 Activity에 여러 번 들어가고 나올 가능성이 크다.
    ex) 사용자가 기기의 뒤로 버튼을 누르는 경우 현재 Activity에서 다른 Activity를 launch하게 된다.

  • Starting one activity from another
    Activity는 보통 특정 시점에서 다른 Activity를 launch해야 하는 경우가 많이 발생한다.
    ex) 앱이 현재 화면에서 새로운 화면으로 옮겨갈 때

현재 Activity가 종료되고 새로 launch하려는 Activity에서 result를 받기를 원하는지 여부에 따라 startActivity()나 startActivityForResult() 메서드 중 하나를 사용하여 새 Activity를 launch한다. 물론 두 가지 경우 모두 Intent 객체를 전달함.

  • startActivity()
    새로 시작된 Activity가 result를 반환받을 필요가 없을 경우, 현재 Activity가 startActivity() 메서드를 호출하면 된다.
val intent = Intent(this, 새롭게 시작할 액티비티명::class.java)
startActivity(intent)
  • startActivityForResult()
    Activity가 종료될 때 result를 반환받고자 할 수도 있는데, 예를 들어 사용자가 연락처 목록에서 어떤 사람을 선택할 수 있도록 하는 Activity를 시작하고 이 Activity가 종료되면 기존 Activity에 선택한 사람을 반환하면 된다.
  • Coordinating activities
    한 Activity가 다른 Activity를 시작하면 두 개의 Activity 모두 lifecycle이 전환된다. 다른 Activity가 생성되는 동안 첫 번째 Activity는 작동을 중단하고 Paused or Stopped state로 들어간다.
    Activity가 디스크 또는 다른 곳에 저장된 데이터를 공유하는 경우, 첫 번째 Activity는 두 번째 Activity가 생성되기 전에 완전히 중단되지 않는다는 점을 이해하는 것이 중요하다. 오히려 두 번째 Activity의 시작 과정이 첫 번째 Activity의 중단 과정과 겹쳐 일어난다.

lifecycle 콜백은 분명히 정의된 순서가 있으며 특히 두 개의 Activity가 같은 프로세스(앱) 안에 있으면서 하나가 다른 하나를 시작하는 경우 순서가 더욱 확실하다.

Activity A가 Activity B를 시작할 때 발생하는 작업 순서는 다음과 같다.

  1. Activity A의 onPause() 메서드가 실행됨.
  2. Activity B의 onCreate(), onStart() 및 onResume() 메서드가 순차적으로 실행됨. (이제 사용자 포커스는 Activity B에 있게 됨.)
  3. 그런 다음, Activity A가 더 이상 화면에 표시되지 않는 경우 이 Activity A의 onStop() 메서드가 실행됨.

이처럼 lifecycle 콜백의 순서는 분명해 예측할 수 있기 때문에 한 Activity에서 다른 Activity으로 전환되는 information을 관리할 수 있는 것이다.

profile
https://github.com/nohjunh

0개의 댓글