본문 바로가기

개발일지

[Android] Activity 생명주기(Life-Cycle)

생명주기(Life Cycle)

: 말 그대로 탄생-죽음에 이르기까지의 과정을 안드로이드 앱에서 적용한다

- Activity, Fragment, Service 총 세 가지 종류의 Lifecycle이 있다

 

Activity Lifecycle (액티비티 생명주기)

: 액티비티가 시작되고 완전히 종료되기까지의 생명주기, 그 액티비티의 상태가 계속해서 변화한다.

ex ) 다른 액티비티에 의해 가려짐 / 전화가 걸려와 액티비티가 가려짐

 

Lifecycle Callback Method

안드로이드 프레임워크에서 제공하는 콜백 메소드 : 액티비티의 상태가 변할 때마다 특정한 동작을 수행하도록 한다

이 수명주기 콜백 메소드를 적절히 구현하면 다양한 문제를 예방하고 앱이 안정적으로 동작하게 할 수 있다

 

: 꼭 구현해야 하는 메서드는 있지만 모든 수명주기를 구현할 필요는 없다,

즉 필요한 수명 주기 메서드를 구현하자

 

 

 

 

핵심적인 콜백 메서드 6가지

onCreate() : 시스템이 액티비티를 생성할 때 실행되는 메서드

- 액티비티 전체 생명 주기 동안 딱 한 번만 동작되는 초기화 및 시작 로직을 실행할 수 있다

ex ) 데이터를 목록에 바인딩, 액티비티를 View Model에 연결, 일부 클래스 범위의 변수를 인스턴스화

※ onCreate()는 다른 메서드들과 다르게 꼭 오버라이딩 하여 구현해야 한다

※ 오버라이딩(Overriding) : 부모클래스의 메서드를 자식클래스에서 재정의해서 사용하는 것

 

 

안드로이드 공식 문서에서 보여주는 onCreate() 구현 예시

/* -- Android Developers Docs에서 보여주는 onCreate() 구현 예시 -- */

lateinit var textView: TextView

var gameState: String? = null 

override fun onCreate(savedInstanceState: Bundle?) {
	super.onCreate(savedInstanceState)
  gameState = savedInstanceState?.getString(GAME_STATE_KEY)

	setContentView(R.layout.activity_main)

	textView = findViewById(R.id.text_view)
}

override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
	textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) 
}

override fun onSaveInstanceState(outState: Bundle?) {
	outState?.run {
		putString(GAME_STATE_KEY, gameState)
		putString(TEXT_VIEW_KEY, textView.text.toString())
	}

	super.onSaveInstanceState(outState)
}
  • setContentView()를 통해서 XML 레이아웃 파일을 넘겨주고 화면에 해당 레이아웃을 그린다
  • setContentView()는 onCreate()에 종속적인 메서드, 반드시 해당 콜백 메서드 안에 구현한다
  • 멤버 변수를 정의하거나 UI를 구성하는 등의 동작

 

onCreate()의 동작이 끝나면 액티비티는 STARTED 상태에 진입, onStart()와 onResume()을 연달아 호출

 

 

onStart() : 액티비티가 onCreate()를 호출한 뒤 STARTED 상태에 진입했을 때 호출되는 메서드

- 액티비티가 사용자에게 보여지고, Foreground Task로서 사용자와 상호작용 할 수 있도록 준비한다

- 매우 빠른 속도로 실행되고, 액티비티가 RESUMED 상태에 진입하며 onResume() 메서드를 호출

 

 

 

onResume() : 액티비티가 RESUMED 상태에 진입하여 Foreground에 액티비티가 표시되고 앱이 사용자와 상호작용 할 수 있는 상태가 된다

  • 어떤 이벤트 및 인터럽트(ex: 전화)가 발생하지 않는 이상, 안드로이드 앱은 RESUMED 상태에 머무른다
  • Foreground에서 사용자에게 액티비티가 보여지는 동안 실행하는 모든 기능을 활성화 할 수 있다
  • 방해 이벤트 및 인터럽트로 PAUSED 상태에서, 전화를 다 받거나 하면 액티비티는 RESUMED 상태로 돌아오며 다시 한 번 onResume()을 호출한다 -> 즉, onPause() 중에 해제되는 구성요소를 다시 초기화하는 작업을 수행
class CameraComponent: LifeCycleObserver {
	...
	
	@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)	
	fun initCamera() {
		if (camera == null) {
			getCamera()
		}
	}

	@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
	fun releaseCamera() {
		camera?.release()
		camera = null
	}
	...
}

- 액티비티가 RESUMED 상태가 될 때마다 카메라를 초기화하는 예제

- PAUSED 상태가 될 때 메모리에서 카메라를 해제(다른 앱과 시스템 자원 공유를 위해)하기 때문에 다시 초기화한다

 

 

 

 

onPause() : 사용자가 잠시 액티비티를 떠났을 때 호출되는 메서드

  • 방해 이벤트 및 인터럽트가 발생하면 액티비티는 PAUSED 상태에 들어가 onPause() 콜백 메서드를 호출한다
  • 즉, 해당 액티비티가 Foreground에 없다는 것을 의미
  • 따라서 onPause() 에서는 계속 실행되어서는 안되지만 언젠가 다시 시작할 작업을 일시중지한다
  • 또한, 배터리 수명에 영향을 미칠 수 있는 모든 시스템 리소스 등을 할당 해제하여 자원을 효율적으로 사용

onPause()는 아주 잠깐 실행되므로 사용자 데이터 저장, 네트워크 호출, DB트랜잭션 등을 실행하면 안된다

이렇게 무언가를 저장하는 큰 작업들은 onStop()에서 수행해야 한다

 

 

 

onStop() : 액티비티가 사용자에게 더 이상 표시되지 않으면 STOPPED 상태에 진입하고, 호출되는 메서드

  • 새로 시작된 액티비티가 화면 전체를 차지할 경우에 해당한다
  • 이 메서드에서는 불필요한 리소스를 해제 or 조정한다

ex ) 애니메이션 일시정지, GPS 위치 인식도를 '세밀한 위치'에서 '대략적 위치'로 전환

 

 

UI 관련 중지 작업 시에는 onPause(), onStop() 중 어떤 것을 사용해야 하는가?

  • onStop()을 사용해야 멀티 윈도우로 동시에 두 앱을 구동시켜도 애니메이션 같은 UI 구성요소가 멈추지 않는다
  • 멀티 윈도우의 다른 앱으로 포커스를 조정하면 onPause()가 호출되기 때문
  • onPause() 내에 UI 중지 작업을 수행하면, 멀티 윈도우 상으로 액티비티가 표시되고 있어도 UI가 멈춘다
  • 또한, CPU 소모가 큰 작업을 종료해야 한다
  • 어떠한 정보를 DB에 저장할 타이밍을 모르겠다면 onStop()에 저장!
override fun onStop() {
	super.onStop()

	val values = ContentValuse().apply {
		put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText())
		put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle())
	}

	asyncQueryHandler.startUpdate(
		token,
		null,
		uri,
		values,
		null,
		null
	)
}

 

 

 

 

 

 

onDestory() : 액티비티가 완전히 소멸되기 전에 호출되는 메서드

 

액티비티가 소멸되는 경우

1. finish() 호출

2. 사용자가 앱을 종료한 경우

3. 화면 구성이 변경(기기 회전 등)되어 일시적으로 액티비티를 소멸시키는 경우 

 

액티비티가 종료되면 onDestory()가 마지막 라이프사이클 콜백 메서드

3번 사유로 호출된다면, 시스템은 즉시 새롭게 변경된 액티비티 인스턴스를 생성하여 onCreate()를 호출한다

 

만약 onDestory()가 호출되기 까지 해제되지 않은 리소스가 있다면, 모두 여기서 해제해주어야 한다!

Memory Leak(메모리 누수) 위험이 있기 때문.

 

이후, 액티비티는 메모리 상 완전히 소멸된다