[Android] Activity, Fragment 생명주기

이동건·2023년 5월 10일
1

android

목록 보기
1/3

안드로이드 기본적인 지식을 다시 공부하고 있는데 생명주기가 생각보다 헷갈려서 이 기회에 정리해보고자 한다.

Activity 생명주기

액티비티는 시작되고 종료될 때 까지 액티비티의 상태가 계속 변하게 되는데, 새로운 상태로 전환되면 시스템은 콜백 메서드를 호출한다. 콜백 메서드에는 onCreate, onStart, onResume, onStop, onDestroy 이렇게 6가지가 존재한다.

onCreate

시스템이 액티비티를 생성할 때 실행된다. 전체 생명 주기 동안 한 번 만 발생해야 하는 기본 로직을 실행한다.

  • UI 선언(xml 파일 setContentView)
  • ViewModel 연결
  • Bundle 객체 수신
  • 멤버 변수 정의

onCreate의 동작이 끝나면 액티비티가 STARTED 상태에 진입하게 되어 시스템은 onStart와 onResume을 연달아 호출한다.

onStart

액티비티가 STARTED 상태에 진입할 때 호출되며, 액티비티가 사용자에게 보여진다. 포그라운드 태스트로써 사용자와 상호작용 할 수 있도록 준비한다. 이 메서드에서 UI를 관리하는 코드를 초기화한다.

  • 애니메이션 처리

onStart 메서드는 매우 빠르게 완료되며 완료된 후에 액티비티는 RESUMED상태로 진입하게 되며, onResume을 호출한다.

onResume

액티비티가 RESUMED 상태에 진입하면 포그라운드에 표시되며, 앱이 사용자와 상호작용 하게 된다. 어떤 이벤트가 발생해서 해당 화면이 포커스가 떠날 때 까지 앱이 이상태에 머무른다. 예를 들어 전화가 오거나, 사용자가 다른 활동으로 이동하거나, 기기 화면이 꺼지는 이벤트가 해당된다.

즉, 액티비티가 포그라운드에서 벗어나기 전까지는 RESUMED 상태를 유지한다. 만약 방해되는 이벤트가 발생하면 PAUSED 상태로 진입하며, 시스템은 onPause를 호출한다.

onPause

시스템은 사용자가 액티비티를 떠나는 것을 나타내는 첫 번째 메서드로 호출한다. 액티비티가 항상 소멸되는 것은 아니지만, 포그라운드에 있지 않게 되었다는 것을 나타낸다. 예를 들어 새로운 반투명 액티비티가 보이거나 멀티 윈도우 모드에서 포커스가 다른 앱으로 변경된 경우 호출된다.

예외 : 멀티 윈도우 모드에서는 다른 앱에 포커스를 두어도 해당 액티비티가 포그라운드에 있어도 onPause가 호출된다.

onPause는 액티비티가 일시 정지 되었을 때는 계속 실행되면 안 되지만, 잠시 후 다시 시작할 작업을 일시 중지하거나 조정한다.

  • 포커스 상실 시 원하는 스레드 및 코루틴 중지
  • 카메라 프리뷰 화면 해제

하지만 onPause에서 상태 저장 및 복원을 하면 안된다!. onPause는 정말 짧게 실행되므로, 저장 및 요청 작업을 처리하기엔 시간이 부족할 수 있다. 이러한 작업은 메서드 실행이 끝나기 전에 완료되지 못할 수도 있다. 부하가 큰 종료작업은 onStop에서 진행하자!

onStop

액티비티가 사용자에게 더 이상 표시 되지 않으면 STOPPED 상태에 들어간다. 이는 새로 시작된 액티비티가 화면 전체를 차지하는 경우이다. 홈 버튼을 눌러 홈화면으로 가거나 화면을 끈 경우에 호출된다.

onStop에서는 앱이 사용자에게 보이지 않는 동안 앱이 사용하지 않은 리소스를 해제하거나 조정해야 하한다.

  • 애니메이션 해제
  • 세밀한 위치 업데이트에서 대략적인 위치 업데이트로 전환
  • CPU를 비교적 많이 소모하는 작업 종료

멀티 윈도우 모드를 고려하면, UI 관련 중지 작업은 어떤 것을 사용해야 하나요?!
: onStop()을 사용해야 멀티 윈도우를 사용하여 동시에 두 앱을 구동하고 있어도 애니메이션 등 UI 구성 요소가 멈추지 않는다. 다른 앱으로 포커스를 옮기면 onPause()가 호출되기 때문이다. onPause에서 이러한 작업을 하게 되면, 액티비티가 화면에 보이는데도 UI는 제대로 작동 안할 수 있다.

onDestroy

액티비가 소멸되기 전에 호출된다. 시스템은 다음 중 하나에 해당할 때 이 콜백을 호출한다.

  • 사용자가 직접 액티비티를 닫거나 finish()가 호출되어 종료되는 경우
  • 구성 변경으로 인해 시스템이 일시적으로 활동을 소멸시키는 경우

onDestroy에서 이전의 onStop에서 해제되지 않은 모든 것을 해제해야 한다.


Fragment 생명주기

Fragment는 독립적으로 존재하지 못하고 항상 액티비티 내에서 호스팅되어야 한다. 하지만 독자적인 Lifecycle을 가진다. onStart ~ onStop은 비슷하지만, 나머지 콜백 메서드 중 차이점이 존재한다.

onAttach

프래그먼트가 액티비티에 연결될 때 호출된다.

onCreate

프래그먼트가 액티비티의 호출을 받아 생성된다. savedInstanceState(Bundle) 값을 받아온다.

onCreateView

뷰를 inflate하고 리턴한다. 리턴만 하는 곳

onViewCreated

onCreateView()를 통해 반환된 View 객체는 onViewCreated()의 파라미터로 전달된다. 프래그먼트의 뷰가 null이 아닌 값으로 인스턴스화 되는 경우에만 프래그먼트에 설정되고 이 콜백이 호출된다. 이때 View Lifecyle이 INITIALIZED 상태로 업데이트 된다.

  • View의 초기값 설정
  • LiveData 옵저빙
  • RecyclerView 및 ViewPager 어댑터 설정

onViewStateRestored

저장된 Fragment View State가 있는 경우 복원이 이루어지며 이때 호출된다. View Lifecycle이 CREATED로 변경된다.

onStart

액티비티의 onStart와 유사하다. Fragment의 Lifecycle이 STARTED상태로 변경되고 이 직후 View Lifecycle 또한 STARTED 상태로 변경된다.

onResume

액티비티의 onResume과 유사하게 사용자가 프래그먼트와 상호작용 할 수 있을 때 호출된다. 모든 프래그먼트 전환효과가 종료되고 사용자와 상호작용할 준비가 되었다.

onPause

액티비티의 onPause와 유사하다. 이때 프래그먼트와 프래그먼트 뷰의 생명주기는 STARTED가 된다.

onStop

액티비티의 onStop과 유사하게 더 이상 보이지 않을 때 호출된다. onStop은 부모 액티비티나 프래그먼트가 종료되었을 때 뿐만이 아니라 이들이 상태를 저장할 때도 호출이 된다. 프래그먼트와 프래그먼트 뷰의 라이프사이클은 Created가 된다.

API 28이후로 onStop이 onSaveInstanceState보다 먼저 호출된다. 따라서 onStop이 FragmentTransaction을 안전하게 수행하는 마지막 지점이 되었다.

onDestroyView

프래그먼트의 View가 소멸될 때 호출된다. 프래그먼트 자체는 아직 메모리에 남아있으므로, 프래그먼트 뷰에 대한 모든 참조를 제거해야한다!!

프로젝트가 ViewBinding을 사용중이라면, 이 메서드에서 binding 변수를 null로 만들어야 된다.

onDestroy

프래그먼트 자체가 소멸된 경우 호출되며 프래그먼트 생명주기가 종료된다.

onDetach

프래그먼트가 액티비티에서 분리될 때 호출된다.


응용 질문

Q : 시스템에 의해 액티비티가 종료되고 다시 복원되는 경우 어떤 메서드들이 호출되나요?!

UI 상태를 저장하고 복원하는데 사용할 수 있는 것들엔 ViewModel, 저장된 인스턴스 상태, 로컬 저장소(Room DB) 가 있다. 이 중 이 질문에서 포커스 하고자 하는 것은 저장된 인스턴스 상태 이며, 이를 ViewModel에서 SavedStateHandle로 활용하는 것은 여기를 참고하자. 이 페이지에서 답변은 Activity에서 하는 방법 위주로 적었다.

시스템이 RAM 여유 공간이 부족하여 백그라운드에 있는 프로세스(STOPPED 상태)를 종료할때 액티비티에서 onSaveInstanceState()가 호출된다.

override fun onSaveInstanceState(outState: Bundle?) {
    // Save the user's current game state
    outState?.run {
        putInt(STATE_SCORE, currentScore)
        putInt(STATE_LEVEL, currentLevel)
    }

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(outState)
}

액티비티가 소멸된 이 후 재생성되면 Bundle로 부터 저장된 인스턴스 상태를 복구할 수 있다. onCreate()onRestoreInstanceState()둘 다 인스턴스 상태 정보를 포함하는 동일한 번들을 수신한다.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState) // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        with(savedInstanceState) {
            // Restore value of members from saved state
            currentScore = getInt(STATE_SCORE)
            currentLevel = getInt(STATE_LEVEL)
        }
    } else {
        // Probably initialize members with default values for a new instance
    }
    // ...
}

onRestoreInstanceState() 에서도 상태복원이 가능하다. 이는 onStart() 메서드 다음에 호출된다. 시스템은 복원할 저장 상태가 있는 경우에만 호출한다. 따라서 bundle에 null 체크를 할 필요가 없다.

Q : Fragment에서 Lifecycle과 ViewLifecycle에는 어떤 차이점이 있나요?

Fragment에서 View는 Fragment와 생성시점이 다르다. Fragment의 View는 onCreateView, onViewCreated를 호출하며 초기화되지만, Fragment는 onCreate때 생성된다.

또한 제거 시점도 다르다. Fragment의 View는 onDestroyView에서 제거되지만, Fragment는 onDestroy에서 제거된다.

마지막으로 관리방식도 다른데, Fragment는 FragmentManager를 통해 관리되지만 Fragment의 View는 Fragment 자체에 의해 관리된다.


참고

https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko
https://developer.android.com/guide/components/fragments?hl=ko

profile
성장하는 활동적인 개발자

0개의 댓글