안드로이드 활동 생명 주기(Activity lifecycle)
Android 개발자 문서 활동 수명(생명) 주기에 관한 이해
https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko
사용자가 앱을 탐색하고, 앱에서 나가고, 앱으로 다시 돌아가면 앱의 Activity 인스턴스는 생명주기 안에서 서로 다른 형태로 전환된다. Activity 클래스는 사용자의 행동에 따른 상태 변화를 알아차릴 수 있는 여러 콜백을 제공한다.
각 콜백은 상태 변화에 적합한 특정 작업을 실행할 수 있게 한다. 적시에 알맞은 작업을 하고 적절하게 전환을 처리하면 앱이 더욱 안정적으로 기능할 수 있다. 예를 들어, 사용자가 앱을 사용하는 도중에 전화가 걸려오거나 다른 앱으로 전환하여도 앱이 비정상적으로 종료되는 문제를 예방할 수 있다.
활동 생명 주기
활동 생명 주기 단계 간에 전환하기 위해 활동 클래스는 6가지 콜백 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()를 제공한다.
onCreate()
- 시스템이 Activity를 생성할 때 전체 생명 주기 동안 가장 먼저, 한 번만 발생하는 기본 애플리케이션 시작 콜백
- 호출 시 Activity 코드에 새로운 View 객체를 생성하며 'Created(생성됨)' 상태가 되고, 실행을 완료하면 'Started(시작됨)' 상태가 됨
- 이어서 시스템은 onStart(), onResume() 메서드 호출
onStart()
- Activity가 'Started' 상태가 되면 호출되는 콜백
- 호출 시 Activity가 사용자에게 표시되고, 앱은 Activity를 포그라운드에 보내 상호작용을 할 수 있도록 준비함
- 실행을 완료하면 'Resumed(재개됨)' 상태가 되며, 시스템은 onResume() 메서드 호출
onResume()
- 앱이 사용자와 상호작용하며, 어떤 이벤트가 발생하여 앱에서 포커스가 떠날 때까지 앱이 이 상태에 머무름
- 생명 주기 구성요소가 포그라운드에서 사용자에게 보이는 동안 실행해야 하는 모든 기능을 활성화할 수 있음
- 방해되는 이벤트가 발생하면, 'Paused(일시중지됨)' 상태가 되고, 시스템은 onPause() 메서드 호출
- Paused→Resumed 상태로 돌아오면, 시스템은 다시 한 번 onResume() 메서드를 호출하여 초기화 작업 수행
- 멀티 윈도우 모드일 때는 @@
onPause()
- 시스템은 사용자가 Activity을 떠나는 것을 나타내는 첫 번째 신호로 이 메서드를 호출
- Activity가 항상 소멸되는 게 아니라, 포그라운드에 있지 않게 됨
- 'Paused' 상태일 때, 계속 실행되어서는 안되지만 잠시 후 다시 시작할 작업을 일시중지하거나 조정함
포그라운드에 있지 않을 때는 모두 정지할 수 있음 - 시스템 리소스, 센서 핸들 또는 Activity가 일시중지 중이고 사용자가 필요로 하지 않을 때 배터리 수명에 영향을 미칠 수 있는 모든 리소스를 해제할 수 있음
- Activity가 다시 시작되면, 시스템은 다시 한번 onResume() 콜백을 호출함
onStop()
- Activity가 사용자에게 더 이상 표시되지 않으면 'Stopped(중단됨)' 상태가 되며, Activity 객체는 메모리 안에 머무르며, 시스템은 onStop() 콜백을 호출함
- 앱이 사용자에게 보이지 않는 동안 앱은 필요하지 않은 리소스를 해제하거나 조정해야 함
- CPU를 비교적 많이 소모하는 종료 작업(데이터베이스에 저장 등)을 실행해야 함(onPause()는 아주 잠깐 실행되므로 onStop()에서 작업)
- Activity가 다시 시작되면, onRestart()를 호출하며 사용자와 다시 상호작용함
- Activity가 실행을 종료하면, onDestroy()를 호출함
onDestory()
- Activity가 소멸되기 전에 호출되는 콜백
- (사용자가 활동을 완전히 닫거나 활동에서 finish()가 호출되어) 활동이 종료되는 경우
→ Activity가 소멸되기 전에 모든 데이터 정리 - 구성 변경(ex. 기기 회전 또는 멀티 윈도우 모드)으로 인해 시스템이 일시적으로 활동을 소멸시키는 경우
→ 새 Activity 인스턴스 생성 후 새로운 구성에서 그 새로운 인스턴스에 관해 onCreate() 호출 - 이전의 콜백에서 아직 해제되지 않은 모든 리소스(ex. onStop)를 해제해야 함
다른 액티비티가 일부만 가리면 onPause()가 호출되고 전체를 가리면 onStop()이 호출된다. 디바이스의 메모리가 부족해 우선순위가 낮은 앱을 종료해야 한다면 앱은 onPause에서도 종료될 수 있다. 앱이 종료된다고 무조건 onStop()이나 onDestroy()가 호출된다는 보장이 없다. 그래서 주로 onPause() 메서드를 주로 오버라이드하지만 리소스를 안전하게 제거하기 위한 안전장치로 onStop()과 onDestroy()를 호출하는 것도 괜찮다. onDestroy() 메서드는 finish()를 호출할 때 말고 시스템에 의해서 제거될 때도 호출된다. 앱에서 하나의 태스크를 사용하면 메모리가 많아질 때 OutOfMemoryError가 발생하지만 여러 태스크를 사용한다면 가용 메모리의 3/4가 넘을 때 백그라운드 태스크의 액티비티를 제거한다. 시스템에 의해서 태스크의 액티비티 목록이 제거될 수 있으므로 액티비티 개수나 액티비티 목록을 메모리에 유지하는 방식은 사용 하지 않는 게 좋다. 주의해야할 생명주기 호출 시점이 있다. 먼저 onCreate()에서 finish 메서드가 호출되면 바로 onDestroy가 호출된다. 두 번째로 onActivityResult() 메서드는 onResume()보다 먼저 실행된다. 따라서 순서에 유의해 UI를 업데이트 해야 한다.
생명 주기 메서드 호출 순서
시작할 때 : onCreate → onStart → onResume
화면 회전할 때 : onPause → onStop → onDestroy → onCreate → onStart → onResume
다른 activity가 위에 뜰 때/전원 키로 화면 OFF할 때/홈 키 : onPause → onStop
백 키로 activity 종료할 때 : onPause → onStop → onDestroy
백 키로 기존 activity에 돌아올 때/홈 키로 나갔다가 돌아올 때 : onRestart → onStart → onResume
다이얼로그 activity나 투명 activity가 위에 뜰 때 : onPause
Activity 전환 시 생명 주기 메서드 호출
- Activity A에서 Activity B를 시작할 때
Activity A는 onPause 메서드를 호출해 백그라운드 상태가 됨
Activity B는 onCreate, onStart, onResume를 호출하고 포그라운드 상태가 됨
만약 Activity B가 전체 화면을 덮어서 A가 보이지 않으면, A는 onStop을 호출함
만약 Activity B가 투명하거나 일부만 덮으면, A는 onStop이 아닌 onPause를 호출함 (A에서 저장하던 값을 B가 onCreate에서 사용해야 할 때)
- Activity B에서 다시 Activity A가 실행될 때
Activity B는 onPause 메서드를 호출해 백그라운드 상태가 됨
Activity A는 onRestart, onStart, onResume 메서드를 호출해 포그라운드 상태가 됨
Activity B는 onStop, onDestroy 메서드를 호출해 종료됨