생명주기의 사전적 정의를 살펴보면 "어떤것이 태어나고 죽기까지의 기간"을 말한다고 나와있다
사람으로 예를들어보면, 사람은 태어나고 죽기까지의 생명주기를 가지며 이 생명주기동안 사람은 어린아이에서 어른이, 어른에서 노인이되는 과정을 거치게된다
그런데 안드로이드의 Activity도 이렇게 생성되고 소멸되기까지의 생명주기를 가지고있다
이런과정은 여러함수들로 구성이 되어있는데 이런 함수들을 총칭해서 Activity 생명주기라고 부른다
그래서 이런 Activity 생명주기를 사용하면 프로그램을 더욱 안정적으로 구현할수있게된다
먼저 이런 Activity 생명주기를 왜 사용해야되는지 예를 들어서 설명해보면
휴대폰으로 게임을하고있는 도중에 전화가 왔다고 해보자
그러면 보통 게임이 일시정지가 되고, 전화를 마치게되면 다시 게임으로 돌아가서 "계속 하시겠습니까?"라는 알림창이 뜨고 계속하기 버튼을 누르면 게임이 재게되는것을 확인할수있을것이다
이렇게 하려면 어떻게 해야될까? 개발자의 입장에서는 어떤 상태변화에 대해 체크를 해서 이에 적합한 무언가를 해줘야할것이다. 그래서 이런것들을 가능하게 해주는 것이 Activity 생명주기이다!
그런데 휴대폰과 달리 컴퓨터에서는 생명주기가 활용되는것을 거의 본적이 없을것이다
예를 들어 컴퓨터에서 게임을 하던중에 전화가 오면 화면 구석 어딘가에 전화가 왔다는 알림이 작게 뜨고 게임은 그대로 작동할것이다. 이는 모바일과 컴퓨터는 본질적으로 화면의 크기에서 차이가 나기 때문이다
모바일은 화면이 작기때문에 어떤 이벤트가 발생할때마다 자꾸 화면이 가려지게 된다. 그래서 Activity가 생성되고 소멸되기까지 언제 화면이 바뀌는지, 어떤시점에 화면이 가려지는지를 체크해줄 필요가있다
이제 Activity 생명주기가 어떻게 동작하는지 자세히 알아보자!
그림을 보면 Activity가 생성되고 소멸되기까지 여러 함수들로 구성되있는것을 볼수있을것이다
각 함수들이 어떤상태에서 호출되는지, 보통 각 함수들에서는 어떤작업들을 하는지 알아보자
# onCreate()
- 최초 실행시에만 해줘야하는 작업들 수행!!
Activity가 생성되고 가장먼저 호출되는 함수로, 최초실행시에만 해줘야하는 작업들을 보통 이함수에서 진행한다.
Data Binding , View 생성 , setContentView와 같은 작업들을 수행한다.
생태변화에 따른 특별한 목적을 가진 작업을 수행하는 것이 아니라면, 대부분의 코드가 onCreate()함수에서 작업이 수행되기 때문에 여태 우리가 가장 많이 사용해봤던 함수일것이다
onCreate()함수가 호출된 후에는 onStart()가 호출되는데, 이때는 강제종료가 불가능하다
# onStart()
- Activity가 사용자에게 보여지기 직전에 호출!!
- 화면에 진입할때마다 실행되어야하는 작업들 수행
이렇게 onCreate()함수가 호출되고나면 바로 이어서 onStart()함수가 호출되는데
onStart()함수는 onCreate()이후에 바로 호출되는 함수로, Activity가 사용자에게 보여지기 직전!!에 호출된다
이후에 onResume()으로 이어진다.
여기서는 화면에 진입할때마다 실행되어야하는 작업들 수행하는데 보통 UI를 관리하는 코드를 초기화한다던지, onStop()함수에서 해제된 리소스 초기화를 한다
# onResume()
- onResume()은 Activity가 사용자와 상호작용하기전에 호출
- 사용자에게 보이는동안 실행해야하는 기능
onStart()함수가 호출되고 나면 바로 이어서 onResume()함수가 호출된다
onResume()은 Activity가 사용자와 상호작용하기전에 호출되며, 호출되고나면 Activity와 사용자가 상호작용하기 시작한다
Activity와 사용자가 상호작용한다는것은 Activity가 정상적으로 실행되고 있다는 뜻이다
그래서 이곳에서는 사용자에게 보이는동안 실행해야하는 기능을 작업하는데, 예를들어 카메라 어플의 경우라면
카메라를 보통 이 함수에서 활성화를 한다. 이외에도 onPause() 에서 해제된 리소스 초기화, 화면이 재개됨 상태로 전환될때마다 필요한 다른 초기화 작업을 한다
활성화 상태에 있다가 다른 Activity가 활성화되면 onResume()이 실행되며, 실행중에 다른 Activity가 활성화되어있을때 기존 Activity가 화면에 보이면 onPause()에서 처리하고, 보이지 않으면 onStop()에서 처리하게 된다
onResume()함수가 호출되고 나면, 이제 Activity가 정상적으로 실행이 된다
따라서 onCreate(), onStart()와 다르게 바로 다음 생명주기 함수를 호출하는것이 아니라 전화가 온다던지, 다른 엑티비티로 이동한다던지, 홈버튼을 눌러서 화면이 꺼지는것과같은 특별한 이벤트가 발생하여 , 엑티비티에서 사용자의 포커스가 떠날때까지 계속 이상태에 머무르게된다
# onPause()
- 잠시후 다시 시작할 작업을 일시중지 or 조정
onPause()함수는 Activity가 정상적으로 실행이 되고 있었다가, 어떤 이벤트가 발생해서 사용자가 Activity에서 떠나게되면 첫번째신호로 호출되는 함수이다.
즉, Activity가 현재 최상단에 있지 않게된 상태(포커스를 잃게된 상태)를 의미한다
아까 게임화면 이미지를 통해 설명해보면, "계속 하시겠습니까?"라는 알림창이 뜬 부분을 보면 가장 상단에 있는것은 뒤에 있는 Activity가 아니라 현재 떠있는 작은 알림창일것이다. 이런 상황에서 뒤에 있는 Activity가 포커스를 잃었으니, onPause()함수가 호출된다고 생각하면 된다
따라서 이함수에서는 잠시후 다시 시작할 작업을 일시중지 or 조정한다.
또는 배터리 수명에 영향을 미칠수있는 리소스 해제한다. 예를들어서, 현재 사용자가 화면을 보고있지 않은데 계속 GPS가 활성화되어있거나 카메라가 켜져있거나 Thread가 계속 실행되는 상황이 발생해서는 안되기 때문이다
onPause()함수도 onResume()함수와 마찬가지로 바로 다음함수인 onStop()함수를 호출하는것이 아니라, 사용자가 다시 돌아올때까지 이 상태에 머무르게된다
그러다가 사용자가 다시 Activity로 돌아오게되면 Activity를 다시 정상적으로 실행시켜야되기 때문에 onResume()함수로 다시 돌아가서 시작하는것을 볼수있다
onResume()에서는 onPause()에서 해제,중지되어도 리소스들을 다시 활성화를 시켜야되기 때문에 onResume()에서는 onPause()에서 해제된 리소스 초기화 혹은 화면이 재개됨 상태로 전환될때마다 필요한 다른 초기화작업을 하는것이다
# onStop()
- Activity가 완전히 가려져서 사용자에게 더이상 보여지지 않을때 호출
- 사용자에게 보이지 않는동안 필요하지 않은 리소스를 해제 or 조정
onStop()은 Activity가 완전히 가려져서 사용자에게 더이상 보여지지 않을때 호출되는 함수이다
예를들어, Activity 전환을 했을때 전체화면이 새로운 화면으로 가려지는 경우가 이에 해당한다 (또한 폰의 알람이 울리거나 전화가 오는경우도 해당)
여기서 onPause()와 onStop()의 차이를 분명하게 구분할줄 알아야된다
onPause()는 Activity가 최상단에 있지 않을때(포커스를 잃었을때)호출되는것이고, onStop()은 화면이 완전히 가려졌을때 호출되는 함수이다.
예를 들어, 이 화면을보면 뒤에있는 반투명한 Activity는 부분적으로는 보이지만 최상단에 있지 않기때문에 포커스를 잃은 상태라고 할수있다. 이때는 Activity가 완전히 가려진것은 아니고 단지 포커스를 잃은것이기 때문에 onPause()까지만 호출이 된다. (onStop()까지는 호출이 되지않음)
반면, Activity전환을 한 경우나 전화가 온 경우에는 새로운 Activity가 기존에 보고있던 Activity를 완전히 가려버리는것이기 때문에 이때는 onStop() 함수까지 호출이 된다. 즉, onStop() 함수는 Activity자체가 완전히 가려졌을때 호출
onStop() 함수가 호출되고나면 Activity가 다시 전면에 보일때까지 해당 상태에 머무르게되며, 다시 사용자가 Activity를 전면에 띄우게 되면 Activity를 실행시켜주기위해서 onRestart()함수를 거쳐서 onStart()부터 다시 호출하면서 Activity를 정상적으로 실행시켜주게 된다
그렇기때문에 onStart()에서는 onStop()에서 해제되었던 리소스를 다시 초기화 시켜줘야한다
# onRestart()
onRestart()는 화면이 가려졌다가 다시 돌아왔을때만 호출되는 함수이다
따라서 onRestart()는 onStop()을 거쳤을때만 실행된다
# onDestroy()
- 엑티비티가 소멸되기 직전에 호출
onDestory() 함수는 Activity가 소멸되기전에 마지막으로 호출되는 함수로, 사용자가 아얘 Activity 자체를 닫아버리거나 어플을 종료하거나 아니면 finish함수가 호출되어서 Activity가 종료되는 경우가 이에 해당된다
따라서 엑티비티가 소멸되기 전에 마지막으로 정리하는 작업을 수행하며, 아직 미처 해제되지 않은 모든 리소스 해제한다
# 프로세스 종료
- 시스템이 프로세스를 종료할 가능성은 그 시점의 프로세스 상태에따라 선택
- onCreate(), onStart(), onResume() -> 강제 종료될 가능성 거의 없음
- onPause() -> 강제 종료될 가능성 보통
- onStop(), onDestroy() -> 강제 종료될 가능성 높음
시스템은 램의 여유공간이 필요할때 프로세스를 종료하게 되는데, 시스템이 어떤 프로그램을 종료할 가능성은 그시점에 그 프로세스가 어떠한 상태에 있느냐에 따라서 달라진다. 시스템은 최대한 사용자가 사용하지 않고있는 백그라운드에 있는 프로세스를 우선적으로 종료한다는것인데 따라서 onCreate(), onStart(), onResume()에서는 프로세스가 강제 종료될 가능성이 매우 낮고, onPause()는 보통, onStop(), onDestroy()에서는 높은편이라고 볼수있다
하지만 요즘 휴대폰들의 성능은 매우 우수하기 때문에 갑작스럽게 프로세스가 종료될 가능성은 적어서 크게 걱정할 필요는 없고 알아만 두면 좋을것같다
# 예제 코드
class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.activity_two)
button.setOnClickListener {
val intent = Intent(this, TwoActivity::class.java)
startActivity(intent)
}
//엑티비티가 생성될때 호출
Log.d(TAG, "onCreate!!")
}
override fun onStart() {
super.onStart()
// 엑티비티가 사용자에게 보여지기 직전에
Log.d(TAG, "onStart!!")
}
override fun onResume() {
super.onResume()
// 엑티비티가 사용자랑 상호작용하기 직전에
Log.d(TAG, "onResume!!")
}
override fun onPause() {
super.onPause()
// 다른 엑티비티가 보일때(중지)
Log.d(TAG, "onPause!!")
}
override fun onStop() {
super.onStop()
// 엑티비티가 완전히 보여지지 않을때
Log.d(TAG, "onStop!!")
}
override fun onDestroy() {
super.onDestroy()
// 엑티비티가 소멸(제거)될때 호출
Log.d(TAG, "onDestroy!!")
}
override fun onRestart() {
super.onRestart()
// 엑티비티가 완전히 가려졌다가 다시 돌아왔을때 호출
Log.d(TAG, "onRestart!!")
}
}
# 실행 화면
1) 앱 실행
앱 실행시에는 onCreate(), onStart(), onResume()이 차례대로 호출되고 엑티비티가 보이게된다
2) "두번째 엑티비티로 이동" 버튼 눌렀을 때
새로운 엑티비티로 이동하게되므로 원래 엑티비티(MainActivity)는 포커스를 잃고 뒤로 가게되고, 최종적으로는 완전히 사용자에게 안보이게 되기 때문에 onPause(), onStop()순으로 호출된다
3) 뒤로가기 버튼을 눌렀을때
원래 엑티비티 화면이 가려졌다가 다시 호출되는것이니깐 onRestart()가 호출된 후
onStart(), onResume() 순으로 호출된다
4) 다시 "두번째 엑티비티로 이동" 버튼 누르면 onPause(), onStop()순으로 호출
5) "첫번째 엑티비티로 이동" 버튼 눌렀을때
다시 첫번째 엑티비티가 실행되므로 onCreate(), onStart(), onResume() 순으로 호출
6) 홈버튼을 눌렀을때
원래 엑티비티가 포커스를 잃게되고 최종적으로 사용자에게 화면이 안보이게되므로 onPause(), onStop()순으로 호출된다
7) 앱을 종료했을때
앱 자체가 종료되었으니깐 엑티비티가 소멸되어서 onDestroy()함수가 호출된다
# 참고한 공식문서와 자료
https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko
https://siadaddy-cordinglife.tistory.com/12
'개발 노트 > Kotlin' 카테고리의 다른 글
버튼 눌렀을때 Fragment화면 나타내기 (0) | 2024.03.28 |
---|---|
코틀린의 ViewBinding과 DataBinding (0) | 2024.03.28 |
프로그래밍 기초 과제 - 계산기 (0) | 2024.03.25 |
버튼에 elevation 속성값을 지정했음에도 그림자가 안보일때 (0) | 2024.03.21 |
ConstraintLayout - chain, bias (0) | 2024.03.21 |