안드로이드에는 필수적인 앱 기본 구성 요소로 activity, service, broadcast receiver, content provider 4가지를 가집니다. 그 중 하나인 activity에 대해 설명하겠습니다.
Activity는 쉽게 말하면 한 화면입니다. 일반적으로 activity는 하나의 화면을 구현하죠. 이메일 앱이 있다고 하면 이메일 목록 화면, 이메일 작성 화면, 이메일 읽는 화면이 있습니다. 총3개의 화면이 있으니 3개의 activity가 있다고 할 수 있습니다. 이렇듯 대부분의 하나의 앱에는 여러 activity로 구성되었죠. Activity는 UI를 그리는 창을 제공하는데 보통 이 창은 화면 전체를 채우지만 한 화면 위에 작은 다른 화면이 떠 있을 수도 있습니다.
일반적으로 앱에서 하나의 activity가 기본 activity로 지정되는데 이는 앱을 실행할 때 표시되는 첫 번째 화면입니다. 다양한 activity을 실행하기 위해 각 activity는 또 다른 activity를 시작할 수 있습니다. 예를 들어 이메일 앱의 기본 activity는 이메일 받은 편지함 화면이며 이 화면에서 이메일 작성 및 개별 이메일 열기 화면을 제공하는 다른 activity들을 실행할 수 있습니다.
모바일 앱은 항상 시작점이 동일하지 않다는 점에서 컴퓨터 앱 환경과 다릅니다. 비결정론적으로 시작되는데 예를 들어 홈 화면에서 이메일 앱을 열면 이메일 목록이 표시되지만 SNS 앱을 사용하고 있는 상태에서 이메일 앱을 실행하면 이메일 작성화면으로 바로 이동합니다. 앱이 다른 앱을 호출할 때 앱 전체를 호출하는 것이 아니라 다른 앱의 activity를 호출하기 때문입니다. 이런 방식으로 activity는 앱과 사용자의 상호작용을 시작하는 역할을 합니다.
Activity 클래스는 이 패러다임을 촉진하도록 설계되었습니다. activity에서 다른 activity를 실행할 수 있기에 의존적이라 생각할 수도 있지만 사실 각자 서로 독립되어있습니다. 각 activity는 다른 activity에 단지 느슨하게 결합되어 있어 최소한의 종속성만 있을 뿐입니다. 그렇기에 이메일 앱에서 허용했다면 다른 앱에서 바로 이메일 작성 화면으로 이동할 수 있고 브라우저 앱은 SNS 앱의 공유 활동을 실행할 수 있습니다.
Activity는 시스템과 앱의 주요 상호작용을 다음과 같이 돕습니다.
-사용자가 화면에서 현재 관심을 가지는 부분을 추적하여 시스템이 그에 대한 activity를 호스팅하는 프로세스를 계속 실행
-이전에 사용된 프로세스 중 중단되었지만 사용자가 다시 찾을 만한 activity의 프로세스를 유지하는 데 더 높은 우선순위를 부여
-앱이 프로세스를 종료하여 복원된 이전 상태를 가진 채 해당 activity로 돌아갈 수 있게 도움
-앱들이 서로 간의 사용자 플로우를 구현하고 시스템이 이러한 플로우를 조정하기 위한 수단을 제공. 대표적인 예로 공유
Activity를 능숙하게 관리하면 다음과 같은 사항이 보장됩니다.
-사용자 환경에 지장을 주지 않으면서 방향 변경이 원활하게 이루어짐
-activity 전환 과정에서 사용자 데이터가 손실되지 않음
-적절할 때에 시스템이 정상적으로 프로세스를 종료
❓❓❓
첫 번째 사항에 의문을 가질 수 있습니다. 방향 변경을 원활하게..? 그냥 휴대폰을 돌리면 되는 거 아닌가? 사실 화면의 가로 방향 세로 방향은 각각의 activity를 가집니다. 즉 세로 방향에서 가로 방향으로 단말기를 돌리면 세로 방향이었던 activity가 삭제되고 가로 방향의 activity가 생성됩니다. 그렇기 때문에 기존 방향에 있던 데이터가 새로 바뀐 방향의 activity에 지워지지 않고 보존되도록 설정을 해야 합니다. 이에 대한 자세한 내용은 추후 다르도록 하겠습니다.
Activity는 Activity 클래스의 서브클래스로 구현됩니다. Activity 클래스는 Android 앱의 중요한 구성요소로 activity가 실행되고 결합되는 방식은 애플리케이션 플랫폼 모델의 기본 요소입니다. main() 메서드를 사용하여 앱을 실행하는 프로그래밍 패러다임과 달리 Android 시스템은 수명 주기의 특정 단계에 해당하는 특정 콜백 메서드를 호출하여 Activity 인스턴스의 코드를 시작합니다.

앱에서 activity를 사용하려면 manifest폴더의 AndroidManifest.xml 파일에 activity 관련 정보를 등록을 해야 합니다. <activity> 요소를 <application> 요소의 하위 요소로 추가해야 하는데 activity의 클래스 이름을 뜻하는 android:name는 필수로 입력해야 합니다. 새 프로젝트의 manifest파일을 보면 <activity android:name=".MainActivity">라는 코드가 자동으로 생성되는데 이는 기본으로 생성된 activity를 의미합니다. name의 값은 activity의 자바파일 명을 입력하면 됩니다.
Activity는 수명 주기 전체 기간에 걸쳐 여러 상태를 거칩니다. 사용자가 앱을 사용하고 나간 후 다시 돌아오면 서로 다른 상태를 거치며 전환됩니다. 이때 Activity 클래스는 시스템의 상태 변화를 알아차릴 수 있는 여러 일련의 콜백을 제공합니다. 이러한 수명 주기 콜백 메서드에서는 activity가 작동하는 방식을 선언할 수 있습니다. 예를 들어 스트리밍 동영상 플레이어를 빌드하는 경우,
즉, 각 콜백은 상태 변화에 적합한 특정 작업을 실행할 수 있도록 합니다. 적시에 알맞은 작업을 하고 적절하게 전환을 처리하면 앱이 더욱 안정적으로 기능할 수 있습니다.
사용자가 activity를 벗어나면 시스템은 activity를 해체할 메서드를 호출하는데 어떤 경우에는 부분적으로만 해체하기도 합니다. 이때 사용자가 단지 다른 앱으로 전환한다면 이전 activity는 여전히 메모리 안에 남아 있어 포그라운드로 다시 돌아올 수 있습니다. 사용자가 해당 activity로 돌아오는 경우 사용자가 종료한 지점에서 재시작됩니다. 몇 가지 예외를 제외하고 앱은 백그라운드에서 실행될 때는 activity를 실행할 수 없습니다.

Activity 수명 주기 단계 간에 전환하기 위해 Activity 클래스는 6가지 콜백으로 구성된 핵심 집합의 onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()를 제공합니다. activity가 새로운 상태에 들어가면 시스템은 각 콜백을 호출합니다. 또한 시스템은 그 시점의 activity 상태에 따라 특정 프로세스와 그 안의 activity를 함께 종료할 여부를 결정합니다. 일부 작업은 activity 수명 주기 메서드 그 자체에 속해 있지만 종속적인 구성요소의 작업을 구현할 때는 해당 구성요소 안에‘만’ 넣어야 합니다. Activity의 복잡도에 따라, 모든 수명 주기 메서드를 구현할 필요가 없는 경우도 있지만 각각의 수명 주기 메서드를 이해하고, 사용자가 예상한 대로 앱이 동작하도록 필요한 수명 주기 메서드를 구현하는 것이 중요합니다.

Activity가 생성되면 Created 상태가 됩니다. 그러면 onCreate()가 실행되는데 이 메서드에서는 activity의 전체 수명 주기 동안 한 번만 발생해야 하는 기본 애플리케이션 시작 로직을 실행합니다.그렇기에 필수적으로 구현해야하며 필요한 구성요소를 초기화해야 합니다. 예를 들어 앱은 여기에서 뷰를 생성하고 데이터를 결합해야 합니다. 또한 activity와 ViewModel를 연결, 멤버 변수 정의, 일부 UI 구성 등의 activity에 관한 기본 설정을 보여줍니다. 이 메서드는 savedInstanceState 매개변수를 수신하는데 이는 activity의 이전 상태를 저장해주는 데이터 전달 객체, Bundle입니다. 처음 생성된 activity인 경우 Bundle 객체의 값은 null입니다.
Activity의 UI를 위한 레이아웃을 정의하는 작업이 가장 중요합니다. XML 레이아웃 파일은 파일의 리소스 ID인 R.layout.activity_main를 setContentView()에 전달하여 지정합니다. 그렇기에 새롭게 만든 프로젝트에 아무런 수정을 하지 않은 채 실행을 하여도 xml 화면이 보이는 것입니다. 기본으로 생성된 MainActivity 파일에는 setContentView()가 포함된 onCreate()가 자동으로 생성되어 있습니다.
Activity는 Created 상태에 머무르지 않습니다. onCreate() 메서드가 실행을 완료하면 Started 상태가 되고, 시스템이 연달아 onStart()와 onResume() 메서드를 호출합니다. onCreate()가 완료되면 다음 콜백은 항상 onStart()입니다.
onCreate()가 종료되면 activity는 Started 상태로 전환되고 시스템은 이 콜백을 호출하여 activity가 사용자에게 표시됩니다. 즉 onStart()부터 화면에 보이기 시작합니다. 이 콜백에는 activity가 포그라운드로 나와서 상호작용을 위한 최종 준비에 준하는 작업을 합니다. 예를 들어 이 메서드에서 앱이 UI를 관리하는 코드를 초기화합니다. Activity가 Started 상태로 전환하면 이 activity의 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 ON_START 이벤트를 수신합니다.
onStart() 메서드는 매우 빠르게 완료되어 Started 상태에 오래 머무르지 않고 콜백이 완료 직후 activity는 Resumed 상태에 들어가고, 시스템이 onResume() 메서드를 호출합니다.
Activity가 사용자와 상호작용을 시작하기 직전에 시스템이 onResume() 콜백을 호출합니다. Activity가 Resumed 상태에 들어가면 포그라운드에 표시되고 앱이 사용자와 상호작용합니다. 실제적으로 앱을 사용할 수 있는 시기가 이 시기입니다. 이 시점에서 activity는 activity 스택의 맨 위에 있으며 모든 사용자 입력을 저장합니다. 어떤 이벤트가 발생하여 앱에서 포커스가 떠날 때까지 앱은 이 상태에 머무릅니다. 예를 들어 전화가 오거나, 사용자가 다른 activity로 이동하거나, 기기 화면이 꺼지기 전까지는 Resumed 상태입니다. 이러한 이벤트가 발생하면 activity는 Paused 상태에 들어가고, 시스템이 onPause() 콜백을 호출합니다. activity가 Paused 상태에서 Resumed 상태로 돌아오면 시스템은 onResume() 메서드를 다시 한번 호출합니다. 따라서 onPause()에서 해제되는 구성요소를 초기화하고, activity가 Resumed 상태로 전환될 때마다 필요한 다른 초기화 작업도 수행해야 합니다.
Activity가 Resumed 상태로 전환되면 이 activity의 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 ON_RESUME 이벤트를 수신합니다. 이 상태에서는 카메라 미리보기같이 수명 주기 구성요소가 포그라운드에서 사용자에게 보이는 동안 실행해야 하는 모든 기능을 활성화할 수 있습니다.

멀티 윈도우 모드에서는 activity가 Resumed가 아닌 Paused 상태에 있더라도 완전히 보일 수 있습니다. 예를 들어 사용자가 멀티 윈도우 모드에 있을 때 다른 창을 탭하면 이전의 activity는 Paused 상태로 전환됩니다. 멀티 윈도우 모드에서 Resumed 상태인 경우에만 카메라를 활성화하고 싶다면 ON_RESUME 이벤트가 실행된 다음에 카메라를 초기화합니다. Paused 상태에만 카메라를 활성 상태로 유지하고 싶다면 ON_START 이벤트가 실행된 이후에 카메라를 초기화해야 합니다.
⚠️⚠️⚠️
activity가Paused상태일 때 카메라를 활성화하면 멀티 윈도우 모드에서Resumed상태에 있는 다른 앱이 카메라에 액세스하지 못할 수도 있습니다. Activity가Paused상태일 때 카메라를 활성 상태로 유지해야 할 수도 있지만, 이 경우 전반적인 사용자 환경이 실질적으로 저하됩니다. 멀티 윈도우 환경에서 공유된 시스템 리소스 제어는 신중히 고민해야 합니다.
어떤 빌드업 이벤트에서 초기화 작업을 실행하든, 빌드업 이벤트에 상응하는 수명 주기 이벤트를 사용하여 리소스를 해제해야합니다.
| 초기화 | 해제 및 종료 |
|---|---|
| ON_START 이후 | ON_STOP 이후 |
| ON_RESUME 이후에 | ON_PAUSE 이후 |
onResume() 뒤에 항상 onPause() 콜백이 나옵니다.
Activity가 포커스를 잃어 부분적으로는 표시되지만 대체로 사용자가 activity를 떠나있을 때입니다. Paused 상태로 전환되고 시스템은 onPause()를 호출합니다. 사용자가 뒤로 또는 최근 버튼을 탭할 때도 생합니다. onPause()가 실행 완료하면, 발생하는 상황에 따라 다음 콜백은 onStop() 또는 onResume()가 됩니다. 사용자가 activity를 떠나는 것이 항상 종료를 원하는 건 아니므로 시스템은 첫 번째 신호로 이 메서드를 우선 호출하기 때문입니다. 단지 activity가 포그라운드에 있지 않습니다. 만약 멀티 윈도우 모드라면 계속 표시 될 수도 있겠죠. 즉 onPause() 메서드를 사용하면 activity가 Paused 상태를 지속하지 않고 다시 시작할 작업을 일시중지하거나 조정합니다.
Paused이 이유는 여러 가지가 있습니다.onPause() 메서드의 실행이 완료되더라도 activity는 Paused 상태로 남아 있을 수 있습니다. 오히려 다시 시작되거나 사용자에게 완전히 보이지 않을 때까지 이 상태에 머무릅니다. Activity가 다시 시작되면 시스템은 다시 한 번 onResume() 콜백을 호출합니다. Activity가 Paused에서 Resumed 상태로 돌아오면 시스템은 activity 인스턴스를 메모리에 남겨두고, onResume()을 호출할 때 인스턴스를 다시 호출합니다. 콜백 메소드 중에 생성된 구성요소를 다시 초기화할 필요는 없습니다. Activity가 완전히 보이지 않게 되면 시스템은 onStop()을 호출합니다.
사용자가 UI 업데이트를 원할 때, Paused 상태의 activity에서도 UI 업데이트를 계속 진행할 수 있습니다. 예시로는 내비게이션 지도 화면 또는 미디어 플레이어 재생 표시입니다. (내비게이션 조건 검색 다이얼로그 켜진 채로 필터링하면 바로 적용) activity가 포커스를 잃더라도 사용자는 UI를 계속 업데이트될 거라 생각하기 때문입니다. 그러니 포커스를 잃었으니 UI 업데이트를 못하겠지? 라는 의문은 하시지 않아도 됩니다. 하지만 멀티 윈도우 모드에서는 여전히 보이는 상태이기에 UI 관련 리소스와 작업을 완전히 해제하거나 조정할 때는 onPause() 대신 onStop()을 사용하는 것이 좋습니다.
⚠️⚠️⚠️
-아주 잠깐 동안만 실행-> 큰 데이터 저장 작업을 실행하기에 시간이 부족
-애플리케이션이나 사용자 데이터 저장, 네트워크 호출, 데이터베이스 트랜잭션 실행X.
-부하가 큰 종료 작업은 onStop()에 실행
센서 핸들(ex.시스템 리소스, GPS) 이나 activity가 일시중지 중이면서 사용자가 필요로 하지 않을 때, 배터리 수명에 영향을 미칠 수 있는 모든 리소스를 해제할 수도 있습니다.
Activity가 Paused 상태로 전환하면 이 activity의 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 ON_PAUSE 이벤트를 수신합니다. 카메라 미리보기 정지같이, 수명 주기 구성요소는 포그라운드에 없으면서 실행하지 않는 기능을 모두 정지할 수 있습니다
Activity가 사용자에게 더 이상 표시되지 않을 때 시스템은 onStop()을 호출합니다. 이는 activity가 제거 중이거나 새 activity가 시작 중이거나, 기존 activity가 Resumed 상태로 전환되면서 사용 중인 activity가 중지되었기 때문에 발생합니다. activity의 실행이 완료되어 종료될 시점에 onStop()을 호출할 수도 있습니다.
onPause() 아닌 onStop()에서 사용하면, 멀티 윈도우 모드에서 activity가 보이더라도 UI 관련 작업 진행 지속 가능Activity가 Stopped 상태에 들어가면 Activity 객체는 메모리 안에 머무르는데 이 객체는 모든 상태 및 멤버 정보를 관리합니다. Window 관리자와는 연결되어 있지는 않습니다. Activity가 다시 시작되면 이 정보를 다시 호출합니다. Resumed상태인 콜백 메서드에서 생성된 구성요소는 다시 초기화할 필요가 없습니다. 또한 시스템은 레이아웃에 있는 각 View 객체의 현재 상태도 기록합니다. 따라서 사용자가 EditText 위젯에 텍스트를 입력하면 해당 내용이 저장되기 때문에 이를 저장 및 복원할 필요가 없습니다. Activity가 중단되면 시스템이 프로세스를 소멸시키더라도 Bundle에 있는 View 객체, EditText 위젯의 텍스트 상태가 그대로 유지되어 사용자가 이 activity으로 돌아오면 이를 복원합니다.
Activity는 Stopped 상태에서 다시 시작되어 사용자와 상호작용하거나, 실행을 종료하고 사라집니다. 시스템은 다시 시작되면 onRestart(), 실행을 완전히 종료하면 onDestroy()를 호출합니다.
Activity가 Stopped 상태로 전환하면 이 activity가 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 ON_STOP 이벤트를 수신합니다. 여기에서 수명 주기 구성요소는 구성요소가 화면에 보이지 않을 때 실행할 필요가 없는 기능을 모두 정지할 수 있습니다.
Stopped 상태의 activity가 다시 시작되려고 할 때 시스템은 이 콜백을 호출합니다. onRestart()는 activity가 중지된 시간부터 activity 상태를 복원합니다. 이 콜백 뒤에 항상 onStart()가 옵니다.
시스템은 activity가 제거되기 전에 이 콜백을 호출합니다. Activity가 수신하는 마지막 콜백입니다. onDestroy()는 일반적으로 activity 또는 activity가 포함된 프로세스가 제거될 때 onStop()에서 해제되지 않는 리소스를 포함하여 activity의 모든 리소스를 해제하도록 구현됩니다.
onDestroy()를 호출합니다.구성 변경으로 인해 onDestroy()가 호출되는 경우 시스템이 즉시 새 activity 인스턴스를 생성한 다음, 새로운 구성에서 그 새로운 인스턴스에 관해 onCreate()를 호출합니다.
Activity가 소멸 상태로 전환하면 이 activity의 수명 주기와 연결된 모든 수명 주기 인식 구성요소는 ON_DESTROY 이벤트를 수신합니다. 여기서 수명 주기 구성요소는 activity가 소멸되기 전에 필요한 것을 정리할 수 있습니다.
시스템은 RAM에 추가 공간이 필요할 때 프로세스를 종료합니다. 시스템이 특정 프로세스를 종료할 가능성은 그 시점의 프로세스 상태에 따라 달라지며 프로세스 상태는 프로세스에서 실행되는 activity 상태에 따라 달라집니다. 아래 의표는 프로세스 상태, activity 상태, 시스템이 프로세스를 종료할 가능성 사이의 상관관계를 나타냅니다.
| 종료될 가능성 | 프로세스 상태 | activity 상태 |
|---|---|---|
| 가장낮음 | 포그라운드(포커스가 가지고 있거나 가질 예정) | Resumed |
| 낮음 | 보임(포커스 상실) | Started/Paused |
| 높음 | 백그라운드(안보임) | Stopped |
| 가장 높음 | 없음 | Destroyed |
onPause()는 단지 포커스를 상실하였을 뿐 백그라운드로 이동하지 않은 상태입니다. 그렇기에 종료될 가능성도 낮은 편이죠. 이런 이유로 중요하거나 영구적인 데이터의 경우 onStop()이 아니라 onPause()에 저장하는 것이 더 안전합니다. 물론 너무 큰 데이터는 안되겠죠.
시스템은 메모리 공간을 확보하기 위해 절대 activity를 직접 종료하지 않습니다. 그 대신, activity를 실행하는 프로세스를 종료하여 activity뿐만 아니라 프로세스에서 실행되는 다른 모든 작업을 함께 소멸시킵니다. 사용자가 직접 설정의 애플리케이션 관리자를 사용하여 해당 앱을 종료하는 방법으로 프로세스를 종료할 수도 있습니다.
일부 사용자 또는 시스템에 의해 발생하는 다양한 이벤트로 인해 Activity가 다른 상태로 전환될 수 있습니다. 가장 대표적인 예로는 세로 모드와 가로 모드 간 방향 변경, 언어 또는 입력 기기 변경이 있습니다.
Resumed , 다른 창의 activity는 Paused 상태를 가짐. 사용자가 앱을 전환할 때마다 onResume()와 onPause() 전환.Paused 상태로 전환, onPause() 호출onResume() 호출)Stopped 상태로 전환, onPause() 및 onStop() 호출onRestart(), onStart() 및 onResume() 호출)onReStart() 없이 onStart() 및 onResume()만 호출onPause()->onStop()->onDestroy()onPause->onStoponRestart->onStart-onResumeonPause->onStoponStart->onResume버전에 따라 동작이 조금씩 다릅니다

아무 생태 변화 없음
- 상태바와 같이 activity가 아니기 때문
- 권한 허용 dialog는 onPause()를 호출
이는 공식 문서를 보면 이해할 수 있습니다.
This method may start an activity allowing the user to choose which permissions to grant and which to reject. Hence, you should be prepared that your activity may be paused and resumed. Further, granting some permissions may require a restart of you application.
(이 method를 사용하면 사용자가 허용할 권한과 거부할 권한을 선택할 수 있는 activity가 시작될 수 있습니다. 따라서 activity가 일시 중지되고 다시 시작될 수 있습니다. 또한 일부 권한을 허용하려면 앱을 다시 시작해야할 수도 있습니다. )
+

공식 문서에서 위와 같은 내용 때문에 dialog을 부르면 onPause()를 호출한다고 아시는 분들이 계시던데(저포함) 위의 대화상자는 activity로 이루어진 dialog을 말하는 것 같습니다. 일반적으로 dialog을 부르면 onPuase()를 호출하지 않습니다.
요약이 정말 잘되어있네요!bb