4대 컴포넌트

9688 단어 AndroidDevAndroidDev

Android Developers를 참고했다.

Android의 4대 컴포넌트는 Activity, Broadcast Receiver, Content Provider, Service가 있다. Fragment를 추가시키기도 한다.

아래의 각 항목은 뚜렷한 목적을 제공한다. 또한, 각자 나름대로의 라이프 사이클을 가진다.

각 컴포넌트는 인텐트를 통해 서로 상호작용한다.

Activity

액티비티는 사용자와 상호작용하기 위한 진입점이다. 가장 흔하게 사용할 수 있을 것이다. 액티비티는 사용자 인터페이스를 포함한 화면 하나를 나타내게 된다.

여러 액티비티는 함께 작동할 수 있지만 서로 독립되어 있다. 만약 카메라 앱이라면 이메일 앱 안의 액티비티를 시작하여 사용자가 새로운 이메일을 작성하고 사진을 공유하게 할 수 있다.

또한, 액티비티는 6가지 콜백으로 구성된 생명주기 관련 메서드들을 제공한다. (onCreate, onStart, onResume, onPause, onStop, onDestroy)

액티비티의 라이프 사이클은 다음과 같다.

onCreate()

최초로 앱을 실행하면 onCreate()가 실행된다.

onStart()

onCreate() 이후에 실행된다. 이 시점부터는 사용자가 액티비티를 시각적으로 볼 수 있다.

onResume()

액티비티가 실제 사용자와 상호 작용이 가능한 포그라운드에 위치하게 되면 onResume()가 호출된다. (액티비티가 사용자와 상호작용하기 바로 직전에 호출된다.) 이 상태를 액티비티가 실행 중인 것으로 볼 수 있다.

onPause()

액티비티가 실행 중인 상태에서 사용자와 상호작용이 불가능한 상태가 되면 onPause()가 호출된다. 다른 액티비티가 보여질 때 호출되는 것이며, 데이터 저장 및 스레드 중지 등의 처리를 하기에 적당한 메서드이다.

onStop()

액티비티가 더 이상 사용자에게 보여지지 않을 때 호출된다. 메모리가 부족할 경우에는 onStop() 메서드가 호출되지 않을 수도 있다.

onRestart()

경우에 따라 호출되는 메서드이다. 액티비티가 멈췄다가 다시 시작되기 직전에 호출되며, onStop() 이후에 호출되게 된다.

onDestroy()

액티비티가 종료되거나 앱 프로세스 자체가 종료되면 onDestroy()가 호출된다. finish() 메서드가 호출되거나 시스템이 메모리 확보를 위해 액티비티를 제거할 때 호출된다.

Fragment

여러 개의 프레그먼트를 하나의 액티비티에 결합하여 창이 여러 개인 UI를 빌드할 수 있다. 또한, 하나의 프레그먼트를 여러 액티비티에서 재사용할 수 있다. 이렇듯 프레그먼트는 액티비티의 모듈식 섹션이라고 생각할 수 있다. 프레그먼트는 자체적인 생명 주기를 가지며, 자체 입력 이벤트를 수신하고, 액티비티 실행 도중 추가 및 삭제가 가능하다.

프레그먼트는 항상 액티비티 내에서 호스팅되어야 한다. 따라서, 프레그먼트 생명 주기는 호스트 액티비티의 생명 주기에 직접적인 영향을 받는다. 가령 액티비티가 일시정지 되는 경우, 내부의 프레그먼트에서도 일시정지되며, 액티비티가 소멸되면 모든 프레그먼트도 마찬가지로 소멸되게 된다.

프레그먼트를 액티비티 레이아웃에 추가하는 경우, 해당 프레그먼트는 액티비티의 뷰 계층 내에서 ViewGroup에 들어가고, 자체적인 뷰 레이아웃을 정의한다. 액티비티 레이아웃 파일에서 <fragment> 속성으로 프레그먼트를 선언하거나, 기존 ViewGroup에 추가하는 방법으로 액티비티 레이아웃에 프레그먼트를 삽입할 수 있다.

프레그먼트를 생성하기 위해 최소한 아래의 생명 주기 메서드를 구현해야 한다.

onCreate()

프레그먼트를 생성할 때 시스템에서 이를 호출한다. 구현 과정에서 프레그먼트의 기본 요소 중, 프레그먼트가 일시정지 되거나 중단 되었다가 재개되었을 때 유지하고자 하는 것을 초기화 해야 한다.

onCreateView()

시스템은 프레그먼트가 자신의 UI를 처음으로 그릴 때 이 메서드를 호출한다. 프레그먼트에 맞는 UI를 그리기 위해 메서드에서 View를 반환해야 한다. 만약 프레그먼트가 UI를 제공하지 않는다면 null을 반환하면 된다.

onPause()

시스템이 이 메서드를 호출하는 것은 사용자가 프레그먼트를 떠난다는 것을 나타내는 첫 번째 신호이다. (주의할 점은 프레그먼트가 항상 소멸 중이라는 것을 말하는 것이 아니다!) 일반적으로 여기서 현재 사용자 세션을 넘어 지속되어야 하는 변경 사항을 커밋한다. 사용자가 돌아오지 않을 수도 있기 때문이다.

프레그먼트의 생명 주기는 액티비티의 생명 주기를 관리하는 것과 매우 유사하다. 액티비티와 마찬가지로 프레그먼트는 다음과 같은 3가지의 상태로 존재할 수 있다.

재개됨 (Resumed)

프레그먼트가 실행 중인 액티비티에 표시된다.

일시 정지됨 (Paused)

다른 액티비티가 포그라운드에 있고 포커스를 갖고 있지만 이 프레그먼트가 있는 액티비티도 여전히 표시된다. (포그라운드 액티비티가 부분적으로 투명하거나 전체 화면을 뒤덮지 않는다.)

정지됨 (Stopped)

프레그먼트가 보이지 않는다. 호스트 액티비티가 정지되었거나 프레그먼트가 액티비티에서 제거되었으나, 프레그먼트는 백 스택에 추가된다. 물론, 정지된 프레그먼트도 여전히 표시는 된다. 모든 상태 및 멤버 정보를 시스템이 보존한다. 하지만, 사용자에게는 더 이상 표시되지 않으며 액티비티를 종료하면 이 또한 종료되게 된다.

액티비티와 마찬가지로 onSaveInstanceState(Bundle), ViewModel 및 영구 로컬 저장소를 결합하여 구성이 변경되고 프로세스가 종료되더라도 프레그먼트의 UI 상태를 보존할 수 있다.

액티비티와 프레그먼트 간의 가장 큰 차이점 중 하나는 백 스택(Back Stack)이다. 액티비티는 정지되면 시스템에서 관리하는 액티비티의 백 스택으로 들어간다. 다만, 프레그먼트는 기본적으로 Back 버튼을 누르는 경우 삭제되며, addToBackStack() 메서드를 호출하는 경우에만 호스트 액티비티에서 관리하는 백 스택으로 들어가게 된다.

프레그먼트가 있는 액티비티의 생명 주기는 해당 프레그먼트의 생명 주기에 직접적인 영향을 미치게 된다. 따라서, 액티비티에 대한 각 생명 주기 콜백이 각 프레그먼트에 대한 비슷한 콜백을 발생시키게 된다.

하지만, 프레그먼트에는 프레그먼트의 UI를 빌드하고 소멸시키는 등의 작업을 수행하기 위해 액티비티와의 고유한 상호작용을 처리하는 몇 가지 생명 주기 콜백이 더 있다. 다음과 같다.

onAttach()

프레그먼트가 액티비티와 연결되어 있었던 경우 호출된다. (여기서 Activity가 전달된다.)

onCreateView()

프레그먼트와 연결된 뷰 계층을 생성하기 위해 호출된다.

onActivityCreated()

액티비티의 onCreate() 메서드가 반환할 때 호출된다.

onDestroyView()

프레그먼트와 연결된 뷰 계층이 제거되는 중일 때 호출된다.

onDetach()

프레그먼트가 액티비티와 연결이 끊어지는 중일 때 호출된다.

호스트 액티비티의 영향을 받는 동안 프레그먼트 생명 주기의 흐름은 위 그림과 같다. 액티비티의 상태에 따라 프레그먼트가 어떤 콜백 메서드를 수신하게 되는지 결정되는 것이다. 액티비티가 onCreate() 콜백을 받은 경우, 해당 액티비티 안에 있는 프레그먼트는 onActivityCreated() 콜백을 받게 되는 것이다.

액티비티가 재개된 상태에 도달했다면, 자유롭게 프레그먼트를 액티비티에 추가하거나 삭제할 수 있다. 즉, 액티비티가 재개된 상태에 있는 동안에만 프레그먼트의 생명 주기를 독립적으로 변경할 수 있다.

Broadcast Receiver

브로드캐스트 리시버는 시스템이 사용자 플로우 밖에서 이벤트를 앱에 전달하도록 하는 지원 컴포넌트이다. 앱이 시스템 전체의 브로드캐스트 알림에 응답할 수 있으며, Broadcast Receiver도 앱으로 들어갈 수 있는 또 다른 명확한 진입점이 될 수 있으므로 현재 실행되지 않은 앱에도 시스템이 브로드캐스트를 전달할 수 있다.

대다수의 브로드캐스트는 시스템에서 발생한다. 화면이 꺼지는 경우, 배터리가 부족한 경우, 사진을 캡쳐한 경우가 해당된다.

앱 또한 브로드캐스트를 시작할 수 있다. Broadcast Receiver는 사용자 인터페이스를 표시하지 않지만, 상태 표시줄 알림을 생성하여 사용자에게 브로드캐스트 이벤트가 발생했다고 알릴 수 있다.

시스템이 이벤트를 앱에 전달하면 인텐트를 통해 전달하게 된다. 브로드캐스트를 수신할 때, 오레오 이전 버전들은 앱이 종료되어도 정상 수신되나, 그 이후 버전은 리소스 낭비를 막기 위해 앱 종료 이후에는 수신되지 않는다.

브로드캐스트는 액티비티 생명주기를 이용한다. 따라서, 액티비티 생명주기 메서드를 활용하여 사용하면 된다. 다만, 브로드캐스트를 사용하기 위해서는 AndroidManifest.xml 파일에 <intent-filter>를 등록해야 한다.

Content Provider

Content Provider는 파일 시스템, SQLite 데이터베이스, 웹상이나 앱이 액세스할 수 있는 다른 모든 영구적인 저장 위치에 저장 가능한 앱 데이터의 공유형 집합을 관리한다.

다른 앱은 컨텐트 프로바이더를 통해 해당 데이터를 쿼리하거나, 컨텐트 프로바이더가 허용할 경우 수정까지 가능하다. 예를 들어, Android 시스템에서는 사용자 연락처 정보를 관리하는 컨텐트 프로바이더를 제공한다.

AndroidManifest.xml 파일에 등록하는 절차를 거친다. 아래가 예시이다.

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.file_provider"
    android:exported="false"
    android:grantUriPermissions="true">

    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_provider" />
</provider>

exported 속성이 핵심이다. 컨텐트 프로바이더가 개발 중인 앱 내에서만 호출한다면 이 옵션은 false로 주거나, 별도로 처리하지 않아도 된다. 하지만, 외부 앱에서 개발 중인 앱을 호출해 데이터를 제공해야 한다면 true로 설정해야 한다.

Service

Service는 여러 가지 이유로 백그라운드에서 앱을 계속 실행하기 위한 다목적 실행점이다. 오랫동안 실행되는 작업을 수행하거나, 원격 프로세스를 위한 작업을 수행한다. 서비스는 UI를 제공하지 않는다.

가령, 서비스는 사용자가 다른 앱을 사용하고 있는 중에도 백그라운드에서 음악을 재생하거나 사용자와 액티비티 간의 상호 작용을 계속 허용하면서 네트워크를 통해 데이터를 가져올 수 있다. 즉, 단말이 항상 실행되어 있는 상태로 다른 단말과 데이터를 주고 받거나 단말의 상태를 모니터링하는 것이다. 따라서, 서비스를 실행해 두면 실행된 상태가 계속 유지되어야 한다. 이를 위해 서비스가 비정상적으로 종료되더라도 시스템이 자동으로 재실행된다.

서비스를 사용하기 위해서는 AndroidManifest.xml 파일에 등록해야 한다. 또, 서비스를 시작하기 위해서는 메인 액티비티에서 startService() 메서드를 호출한다.

아래는 AndroidManifest.xml 파일에 서비스를 등록하는 예시이다.

<service android:name=".MyService" />

서비스 또한 Content Provider와 유사하게 exported 속성을 false하면 서비스를 본인의 앱에서만 사용하고, true로 하는 경우 다른 앱이 액세스할 수 있다.

좋은 웹페이지 즐겨찾기