안드로이드 시스템에서는 제한된 리소스를 효율적으로 관리해야 한다. 그러면서 항상 사용자에게 응답할 수 있어야한다.
따라서, 안드로이드는 앱이 실행되는 프로세스와 앱을 구성하는 모든 컴포넌트의 생명주기와 상태를 전적으로 통제한다. 그래서 안드로이드 앱을 개발할때 생명주기 관리 모델을 이해하는 것이 중요하다! 앱이 실행될때 생길 수 있는 상태 변경에 대처할 수 있는 방법도 잘 숙지해두어야한다.
안드로이드 앱과 리소스 관리
안드로이드 앱은 안드로이드 운영체제 하에 별개의 프로세스로 실행된다. 그리고, 장치의 자원은 무한정 있는 것이 아니라 한정적이다. 이러한 자원이 꽉 차려고 할 때 시스템에서는 메모리 확보를 위해 프로세스를 중단한다.
어떤 프로세스를 중단할까?
importance hierachy(중요도 서열)에 따라 가장 낮은 우선순위의 프로세스부터 시스템이 기능을 수행하는데 충분한 리소스가 확보될 때까지 프로세스를 중단시킨다.
중요도 서열
현재 실행 중인 모든 프로세스의 우선순위와 상태를 고려하여, 결합해 생성한다.
안드로이드 프로세스 상태
↑ 최고 우선 순위 [ 포그라운드 프로세스 - 가시적 - 서비스 - 백그라운드 - 비어있는 ] 최저 우선 순위 ↓
1. 포그라운드 프로세스
화면으로 볼 수 있고, 사용자와 상호작용하므로 가장 높은 수준의 우선순위가 지정되며, 시스템에 의해 제일 마지막에 중단됨.
프로세스가 포그라운드 상태로 되려면 다음 조건을 하나 이상 충족해야 함
- 사용자와 현재 상호작용 중인 액티비티를 호스팅(포함해서 실행)한다.
- 사용자와 현재 상호작용 중인 액티비티에 연결된 서비스를 호스팅한다.
- 중단되면 사용자에게 해를 끼칠 수 있다는 것을 startForeground() 함수를 호출하여 알려 준 서비스를 호스팅한다.
- 자신의 onCreate(), onResume(), onStart() 콜백 함수 중 하나를 실행하는 서비스를 호스팅한다.
- onReceive() 함수를 현재 실행중인 브로드캐스트 수신자를 호스팅한다.
2. 가시적 프로세스
화면으로 볼 수는 있지만 사용자와 상호작용은 하지 않는 액티비티를 포함하는 프로세스. 프로세스의 액티비티를 사용자가 화면에서 볼 수 있지만, 이 액티비티의 화면 일부를 다른 액티비티 (dialog)가 포그라운드로 실행하면서 가리는 경우, 가시적이거나 포그라운드로 실행되는 액티비티와 결합된 서비스를 호스팅하는 프로세스
3. 서비스 프로세스
이미 시작되어 현재 실행 중인 service를 포함하는 프로세스
4. 백그라운드 프로세스
사용자가 화면으로 현재 볼 수 없는 하나 이상의 액티비티를 포함하는 프로세스. 안드로이드 백그라운드 프로세스의 내역을 동적으로 유지 관리하면서 실행 순서에 따라 프로세스를 중단함. 즉, 포그라운드에서 실행한 프로세스 중 가장 오래된 프로세스가 먼저 종료됨
5. 비어 있는 프로세스
실행되는 앱을 포함하지 않으며, 새로 론칭되는 앱을 호스팅하기 위해 메모리에 남아있음. 리소스 해제시 제일 먼저 중단됨
액티비티 스택
새로운 액티비티가 시작되면 스택의 맨 위로 들어간다. 그리고 현재 실행 중인 액티비티는 스택의 맨 위에 위치한다. 그리고 새로운 액티비티가 시작되면 현재의 액티비티는 그 밑으로 들어간다. 또한, 현재의 액티비티가 종료되거나 사용자가 백버튼을 눌러 이전 액티비티로 돌아갔을 때는 현재의 액티비티가 스택에서 꺼내어진다. 시스템의 리소스(메모리 등)가 부족한 경우에는 스택의 제일 밑에 있는 액티비티부터 제거된다.
액티비티 상태
앱이 실행되는 동안 액티비티는 다음과 같이 서로 다른 상태중 하나가 될 수 있다.
- 실행(Running/Active) : 액티비티가 액티비티 스택의 맨 위에 있고, 장치 화면에서 볼 수 있는 포그라운드 태스크이며, 사용자와 현재 상호작용하고 있다. 이런 상태의 액티비티는 시스템 리소스가 부족할 때에도 거의 중단되지 않는다.
- 일시중지(Paused) : 사용자가 화면에서 볼 수 있지만 포커스를 갖고 있지 않는 경우. 현재 실행 중인 다른 액티비티가 이 액티비티의 화면을 부분적으로 가리고 있기 때문. 일시 중지된 액티비티는 메모리에 보존되어 있고, 윈도우 매니저에 연결된 채로 있으며, 자신의 모든 상태 정보를 가지고 있다. 따라서 액티비티 스택의 맨 위로 이동하면 실행 상태로 빨리 복원이 가능하다.
- 중단(Stopped) : 액티비티가 사용자에게 보이지 않는다. 달리 말해, 장치 화면에서 이 액티비티 화면 전체를 다른 액티비티가 가리고 있을 때다. 일시 중지 액티비티 처럼 이 액티비티는 모든 상태 정보를 보존하고 있다. 그러나 시스템 메모리가 부족해지면 종료될 수 있다.
- 소멸(Killed) : 메모리 확보를 위해 런타임 시스템에 의해 액티비티가 종료되었으며, 액티비티 스택에도 존재하지 않는다. 만일 앱에서 요청하면 이 상태의 액티비티는 새로 다시 시작되어야 한다.
구성 변경
액티비티 상태가 동적으로 변경되어 장치 구성이 변경될 수 있는 경우
- 포그라운드와 백그라운드 간의 액티비티 이동
- 메모리 확보를 위해 런타임 시스템이 액티비티를 종료시키는 것
- 화면에 나타나는 액티비티의 모습에 영향을 주는 모든 구성 변경 (장치 방향을 가로 세로 변경하거나, 시스템 폰트 설정을 변경..같은거) → 액티비티 인스턴스를 소멸 및 재생성하여 구성 변경에 응답함
상태 변경 처리하기
- 안드로이드 운영체제가 호출해 주는 상태 변경 함수에서 응답하는 방법 포스팅 예정
- Jetpack 안드로이드 아키텍처 컴포넌트에 포함된 생명주기 클래스를 사용하는 방법 (구글에서 권장하는 새로운 방법) 포스팅 예정
•──⋅참고 자료⋅──•
📚 닐 스미스, [핵심만 골라 배우는 안드로이드 스튜디오 Arctic Fox & 프로그래밍], 제이펍 (2021)