안드로이드/Deep in the AOS

Activity :: 앱 구성 요소 4대 컴포넌트 [ Deep in the AOS ]

 

  • Activity
  • Service
  • Broadcast Receiver
  • Content Provider

각 유형은 뚜렷한 목적을 수행하고 각자 나름의 수명 주기가 있어서 구성 요소의 생성 및 소멸 방식을 정의합니다.

 

액티비티는 사용자와 상호작용하기 위한 진입점

사용자 인터페이스를 포함한 화면 하나를 나타냅니다.

 

Android Develop에선 이메일 앱을 예시로 설명했습니다.

1. 이메일 목록을 표시하는 액티비티

2. 이메일을 작성하는 액티비티

3. 이메일을 읽기 위한 액티비티

우리는 이메일 앱을 사용하게 되면 [1. 이메일 목록을 표시하는 액티비티]가 화면에 표시될 것입니다.

이 목록 중에 읽고 싶은 메일을 누르면 [3. 이메일을 읽기 위한 액티비티]가 화면에 표시됩니다.

이메일을 작성하는 버튼을 누른다면 [2. 이메일을 작성하는 액티비티]가 화면에 표시됩니다.

이와 같이 액티비티 > 다른 액티비티로 전환될 때 인텐트(Intent) 라는 것을 사용합니다.

Intent에 관해서는 다음에 자세히 포스팅해보겠습니다.

 

액티비티의 생명주기

액티비티는 생명주기를 관리하는데, 이 생명주기를 관리하는 주된 목적은 바로

액티비티 상태를 저장하거나 복원하기 위함 입니다.

🤔 이런 액티비티 상태를 왜 저장하고 왜 복원해야 할까요?

액티비티는 DB, Content Provider, File 등 저장될 필요가 있는 메모리의 데이터를 유지할 수 있습니다.

이런 상태 정보를 영속성 상태(Persistent state)라고 합니다.

 

화면에 보이는 사용자 인터페이스는 동적 상태(Dynamic state)라고 합니다.

또는 사용자 인터페이스 상태나 인스턴스 상태라고도 합니다.

앱이 실행되는 동안만 보존이 되기 때문입니다.

예를 들어 이메일 앱에서 이메일을 작성할 때 텍스트를 마구마구 입력해도 입력된 텍스트는 아직 앱의 영속적 상태 데이터로 확정이 되지 않은 텍스트입니다.

이 상황에서 사용자가 다른 액티비티로 전환하고 다시 메일을 작성하는 액티비티로 돌아왔을 때 텍스트가 남아있길 원합니다. (하지만, 액티비티가 다른 액티비티로 전환될 때 기존의 액티비티는 백그라운드 상태가 됩니다. 상태가 저장되어 있지 않으면 당연히 포그라운드로 돌아왔을 때 텍스트는 남아있질 않습니다.)

이 뿐만 아니라, 안드로이드의 경우 화면이 회전(장치를 세우거나 눕힘)할 때 장치의 구성이 변경되므로 액티비티의 인스턴스를 소멸시키고 새로운 인스턴스를 생성합니다. 그래서 값이 유실되기도 합니다.

이런 상황들을 해결하기 위해 동적 상태를 저장해야 합니다.

정리하자면 포그라운드와 백그라운드 액티비티들 간의 매끄러운 전환을 제공하기 위해 액티비티 상태를 저장하고 복원할 수 있어야 합니다.

 

그렇다면 액티비티의 생명주기 메서드는 무엇이 있을까요?

액티비티 생명주기 메서드

흔하게 볼 수 있는 액티비티 생명주기 메서드를 가져왔습니다.

onCreate(Bundle saveInstanceState)

액티비티 인스턴스가 최초로 생성될 때 호출이 됩니다.

대부분 초기화 작업을 진행하며, 동적 상태 정보를 포함할 수 있는 Bundle 객체가 전달됩니다.

// Bundle이 대체 뭐야?

<--

Map형태로 구현된 데이터의 묶음을 Bundle이라고 합니다.

key 값이 String이며, value값에는 Int, String과 같은 간단한 타입부터 시작해서 Serializable, Parcelable같은 복잡한 타입까지 들어올 수 있습니다.

보통 Android 객체를 전달할 때는 Parcelable을 구현한 객체를 전달합니다. (객체를 감싸는 클래스를 Parcel 클래스라고 합니다.)

-->

동적 상태 정보는 직전에 생성되었다가 소멸된 동일한 액티비티의 인스턴스로 부터 받으며, 일반적으로 사용자 인터페이스 상태와 관련되는 데이터 입니다.

 

onRestart()

액티비티가 런타임 시스템에 의해 이전에 중단되었다가 다시 시작될 때 호출됩니다.

 

onStart()

onCreate(), onRestart() 메서드가 호출된 후 바로 호출됩니다.

액티비티의 UI가 곧 User에게 보일 것이라고 액티비티에게 알립니다.

onStart()가 호출된 다음엔 onResume()가 호출됩니다.

 

onResume()

액티비티가 액티비티 스택의 맨 위, 사용자가 현재 실행 중인 액티비티임을 알립니다.

 

onPause()

onPause 이후에는 onResume() or onStop() 둘 중 하나가 호출됩니다.

액티비티가 포그라운드로 돌아가는 경우 계속 실행하기 위해 onResume() 호출되며,

액티비티 UI를 사용자가 볼 수 없게 중단될 때는 onStop() 호출됩니다.

onPause에서 영속적인 데이터를 저장하는 일을 해야하며, 애니메이션과 같이 CPU를 지나치게 사용하는 작업은 중단해야 합니다.

 

onStop()

액티비티가 앞으로 사용자에게 보이지 않을 때 호출됩니다.

이 메서드 호출 다음에는 onRestart() or onDestory() 호출됩니다.

액티비티가 다시 포그라운드로 갈 때는 onRestart()

액티비티가 종료될 때는 onDestroy() 호출됩니다.

 

onDestroy()

액티비티가 소멸될 때 호출됩니다.

자신의 작업을 완료하고 finish() 하거나, 메모리를 해제하거나 구성이 변경되어(가로/세로 화면 전환) 런타임이 액티비티를 종결할 때도 onDestroy()가 호출되니 액티비티가 종료될 때만 onDestroy() 메서드가 호출되는 것은 아니다.

 

동적 상태를 저장하는 것은 어디서 해야할까?

이 동적 상태를 저장하기 위한 메서드 또한 존재합니다.

 

onRestoreInstanceState(Bundle savedInstanceState)

상태 정보가 저장되었던 이전 액티비티 Instance에서 액티비티가 다시 시작하는 경우에 onStart() 메서드가 호출된 후 바로 호출됩니다.

onCreate()와 onStart()가 실행된 이후에 이전 상태를 복원할 때 이 메서드를 사용합니다.

 

onSaveInstanceState(Bundle outState)

동적 상태 데이터(이전의 이메일 작성중인 텍스트 등...)가 저장될 수 있게끔 액티비티가 소멸되기 전에 호출됩니다.

Bundle 객체를 매게변수로 가지며 저장되어야 하는 상태 데이터를 Bundle 객체로 묶습니다.

이 Bundle 객체는 액티비티가 다시 시작될 때 onCreate() 메서드와 onRestoreInstanceState()에 전달됩니다.

 


이번에 액티비티를 정리해보며 액티비티의 개념에 대해 다시 되짚어보고 어지럽힌 방을 다시 정리정돈한 기분이 듭니다.

액티비티의 상태 2가지

1. 영속적 상태 // 앱이 실행되는 동안 File, DB 등에 저장해야 하는 데이터

2. 동적 상태 // UI에 관련되는 데이터 및 액티비티 내부에서 갖고 있는 데이터

이런 액티비티 상태를 저장해야 하는 이유에 대해서도 알 수 있었습니다. // 나중에 복원하기 위해서 ! 사용자의 좋은 경험을 위해 !