
앱이 비정상 종료되지 않고, 의도한 대로 동작하도록 하려면 lifecycle에 대한 이해가 필요하다. 사용자가 앱을 탐색거나 나갔다가 돌아오는 등 앱을 사용하는 과정에 lifecycle 콜백이 언제 실행되는지를 알아보자. 올바른 콜백 메서드에서 작업을 하고 적절하게 전환 처리를 해야 앱이 안정적으로 기능할 수 있다.
lifecycle을 고려하지 않았을 때 흔히 겪을 수 있는 문제는 다음과 같다.
이러한 문제 발생을 예방하기 위해서는 lifecycle 콜백을 잘 구현해야 한다.
액티비티 수명 주기의 콜백 메서드는 6가지가 있다.
onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy()
처음 실행된 액티비티는 onCreate() -> onStart() -> onResume()까지 호출한다. 그리고 setContentView()에서 출력한 내용이 화면에 나온다. onCreate()는 최초 한 번만 호출되고, onStart()나 onResume()은 반복적으로 호출할 수 있으므로 일반적으로 setContentView()는 onCreate()에서 호출한다.
Android Developers 예제 코드
lateinit var textView: TextView
// some transient state for the activity instance
var gameState: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState)
// recovering the instance state
gameState = savedInstanceState?.getString(GAME_STATE_KEY)
// set the user interface layout for this activity
// the layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity)
// initialize member TextView so we can manipulate it later
textView = findViewById(R.id.text_view)
}
// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY)
}
// invoked when the activity may be temporarily destroyed, save the instance state here
override fun onSaveInstanceState(outState: Bundle?) {
outState?.run {
putString(GAME_STATE_KEY, gameState)
putString(TEXT_VIEW_KEY, textView.text.toString())
}
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState)
}
onStart()가 호출되고 액티비티가 사용자에게 표시된다. ON_START 이벤트를 수신한다.onStart() 메서드는 STARTED 상태에 머무는 것이 아니라 빠르게 완료되고, RESUMED 상태로 들어가 onResume()이 호출된다.onResume()이 호출된다. ON_RESUME 이벤트를 수신한다.on_Pause()가 호출된다.onResume()이 다시 호출된다.ON_PAUSE 이벤트를 수신한다.onPause() 대신 onStop() 에서 해제하는 것이 좋다.onPause()는 짧게 실행되므로 데이터를 저장하거나, 네트워크를 호출하거나, 데이터베이스 트랜잭션을 실행하면 안된다. 큰 종료 작업은 onStop() 상태에서 실행한다.onResume() 콜백을 호출한다.onStop()이 호출된다.ON_STOP 이벤트를 수신한다.onStop()이 호출된다.onRestart()를 호출한다. onRestart() -> onStart() -> onResume()onDestroy()가 호출된다.finish()가 호출되어 액티비티가 종료되는 경우ON_DESTROY 이벤트를 수신한다.ViewmModel에 저장해 기기 회전 등의 이유로 destroyed 된 후에 액티비티가 다시 생성될 때 ViewModel을 보존해 액티비티 인스턴스에 전달한다.ViewModel은 onCleared()를 호출해 액티비티 소멸 전 데이터를 정리한다.[Main] onPause()
[Main] onSaveInstanceState()
[Main] onStop()
[Main] onDestroy()
[Main] onStart()
[Main] onRestoreInstanceState()
[Main] onResume()
onPause() - onStop()
onRestart() - onStart() - onResume()
[Main] onPause()
[Detail] onCreate()
[Detail] onStart()
[Detail] onResume()
[Main] onStop()
Detail에서 onResume()이 호출되어 포커스가 넘어가고 나서 Main의 onStop()이 호출된다.
[Detail] onPause()
[Main] onRestart()
[Main] onStart()
[Main] onResume()
[Detail] onStop()
[Detail] onDestroy()
Main 화면이 완전히 표시되지 않는 onStop()까지 호출되었기 때문에 onRestart()가 호출된다. Main의 onResume()이 호출되어 포커스나 넘어간 후 Detail의 onStop()이 호출되고, 이어서 onDestroy()가 호출되어 소멸된다.
기본적으로 리소스 생성과 해제는 대칭으로 한다.
onCreate()에서 생성했다면 onDestroy()에서 해제,
onStart()에서 생성했다면 onStop()에서 해제,
onResume()에서 생성했다면 onPause()에서 해제,