Activity와 Fragment의 생명주기 (2) - Fragment

KwangYoung Kim·2022년 4월 17일
0

들어가며

Fragment도 자체 생명주기를 가지고 있다.
Activity와 같은 이름의 메소드를 호출하는 과정도 있지만 다른 메소드들이 더 있다.(예를 들어 onCreateView() 등)
또한 Fragment는 Activity위에서 동작하기 때문에 Activity의 생명주기와도 연관이 있어 짚어보고 가면 좋을 것 같다.

생명주기 순서

Fragment의 생명주기 메소드 호출 순서는 위와 같다.

Activity와는 조금 다르게 View에 대한 생명주기 메소드들이 들어가있는 것을 볼 수 있다
=> onCreateView(), onViewCreated(), onDestroyView()

Fragment는 Activity나 부모 Fragment에 호스팅 되어야만 존재할 수 있으므로 Fragment가 Activity나 부모 Fragment에 붙을 때 발생하는 메소드가 있는데, 이미지에는 없지만 onCreate()이전, onDestroy()이후에 각각 onAttach()와 onDetach()가 존재한다.

생명주기 메소드

onAttach()

위에서 설명한 대로 Fragment가 Activity나 부모 Fragment에 붙을 때 호출된다.
매개변수로 Activity Context가 넘어오기 때문에 필요한 경우 참조할 수 있다.

onCreate()

Fragment가 생성될 때 호출된다.
Activity와 마찬가지로 초기화 작업을 해주기에 적절하지만 다른 점은 View에 대한 작업을 하지 않는다

onCreate()에서 savedInstanceState라는 Bundle객체가 매개변수로 넘어오게 되는데 Fragment를 처음 생성할 때는 null로 넘어오지만 그 이후에는 non-null 값으로 넘어온다.

Activity와 동일하게 화면회전 등 구성 변경으로 인해 Fragment가 재생성 되었을 때 상태값을 저장해놓고 savedInstanceState에서 가져와 사용할 수 있다.

onCreateView()

Fragment View를 반환하는 메소드로 여기서부터 Fragment View Lifecycle의 시작이다.
반환한 View는 onViewCreated()의 매개변수로 넘어가게 된다.

onViewCreated()

매개변수로 onCreateView()에서 넘겨준 View가 넘어오게 되는데 여기서 UI에 관련된 작업을 하기에 알맞다.
(RecycleView의 adapter 연결 등)

onViewStateRestored()

View의 상태가 모두 복원되었을 때 호출 된다. 따라서 View의 상태값을 체크하기에 알맞다. (체크박스에 체크가 되어 있는지 등)

onStart()

View가 보여지는 시점이다.
Activity의 onStart()시점과 비슷하게 호출된다.

onResume()

View가 유저와 상호작용할 수 있는 상태가 된다.
Activity의 onResume()시점과 비슷하게 호출된다.

여기서 주의해야할 점은,
Fragment와 Activity의 onStart(), onResume() 메소드 들은 특정하게 어떤 게 먼저 호출되는 순서가 없다.
즉 Activity의 메소드가 먼저 호출될 수도, Fragment의 메소드가 먼저 호출될 수도 있다는 이야기이다.

onPause()

Fragment가 일시중지될 때 호출된다. 화면에 보이기는 하지만 포커싱을 잃은상태.
Activity와 동일하다.

onStop()

Fragment가 화면에서 보이지 않게 되었을 때 호출된다.

API 28이전과 이후 onStop() 호출 시점이 달라졌는데
28 이전은 onSaveInstanceState()가 호출된 후 onStop()이 호출되어 이미 상태가 저장된 후 였지만,
28 이후는 onSaveInstanceState()가 onStop() 이후에 호출이 되기 때문에 Fragment의 상태가 저장되지 않은 시점이다.

onDestroyView()

Fragment가 화면에서 벗어 났을 때 호출된다.
여기서 Fragment View의 생명주기가 끝이 난다.
이 시점에서는 Fragment View에 대한 참조가 모두 해제되어야 한다.

onDestroy()

Fragment의 생명주기가 끝이나며 Fragment가 제거 될 때 호출된다.

onDetach()

Fragment가 Activity에서 제거될 때 호출된다.

동작

직접 Fragment를 Activity에 추가해서 실제로 동작하는 과정을 살펴보자

  • Activity에 FirstFragment라는 Fragment를 추가 후 Activity 종료까지
================================================
Activity에 Fragment 추가 후 종료때까지
================================================
Activity: onCreate()
FirstFragment: onAttach()
FirstFragment: onCreate()
FirstFragment: onCreateView()
FirstFragment: onViewCreated()
FirstFragment: onViewStateRestored()
FirstFragment: onStart()
Activity: onStart()
Activity: onResume()
FirstFragment: onResume()
Activity: onPause()
FirstFragment: onPause()
Activity: onStop()
FirstFragment: onStop()
Activity: onDestroy()
FirstFragment: onDestroyView()
FirstFragment: onDestroy()
FirstFragment: onDetach()
  • FirstFragment가 있는 상태로 화면회전 시
================================================
화면 회전으로 인해 종료
================================================
Activity: onPause()
FirstFragment: onPause()
Activity: onStop()
FirstFragment: onStop()
FirstFragment: onSaveInstanceState()
Activity: onDestroy()
FirstFragment: onDestroyView()
FirstFragment: onDestroy()
FirstFragment: onDetach()
================================================
재생성시작
================================================
FirstFragment: onAttach()
FirstFragment: onCreate()
Activity: onCreate()
FirstFragment: onCreateView()
FirstFragment: onViewCreated()
FirstFragment: onViewStateRestored()
FirstFragment: onStart()
Activity: onStart()
Activity: onResume()
FirstFragment: onResume()

Activity를 그냥 종료시켰을 때와 다르게 onSaveInstanceState()가 호출되는 걸 확인할 수 있다.

그리고 화면회전 시에 주의해야할 점이 있는데, Activity에서 재생성 여부를 체크하지 않고 그냥 Fragment를 추가하는 코드를 넣어놨다면 Activity에서는 또다시 새로운 Fragment를 만들어 추가하게 된다.

/**
Activity 코드
재생성 여부를 확인하지 않았을 때
*/

supportFragmentManager.beginTransaction()
	.replace(R.id.container, firstFragment, "FirstFragment")
    .commit()

/**
결과 - 화면회전 후 onCreate()가 두번 호출되는 걸 볼 수 있다.
*/
FirstFragment: onCreate() - FirstFragment{5837380} (76eade5e-8cad-43e1-ad04-d952f3cbdfb4 id=0x7f080081 tag=FirstFragment)
FirstFragment: onCreate() - FirstFragment{a421681} (f4ccb172-1d39-4aea-894a-ae7935bcdcb9 id=0x7f080081 tag=FirstFragment)

이유는 이미 추가되었던 Fragment들은 FragmentManager에 의해 구성변경(화면회전 등)에도 살아남아 관리된다.
그렇기 때문에 Activity가 재생성된다고 해서 새로 추가해줄 필요가 없다.

  • FirstFragment에서 SecondFragment로 교체 시
================================================
Fragment 교체
================================================
FirstFragment: onPause()
FirstFragment: onStop()
SecondFragment: onAttach()
SecondFragment: onCreate()
SecondFragment: onCreateView()
SecondFragment: onViewCreated()
SecondFragment: onViewStateRestored()
SecondFragment: onStart()
FirstFragment: onDestroyView()
FirstFragment: onDestroy()
FirstFragment: onDetach()
SecondFragment: onResume()

마치며

Activity와 Fragment의 생명주기에 대해 정리해보았는데 까다로운 생명주기 관리를 도와주는 AAC 라이브러리들이 존재한다.
ViewModel, Lifecycle 등...
생명주기에 대해 공부했다면 위와 같은 라이브러리를 잘활용하여 어려울 수 있는 생명주기 관리를 조금 더 수월하게 할 수 있을 것 같다.

출처 / 참고 -
https://readystory.tistory.com/199
https://www.charlezz.com/?p=442

profile
축구왕이 되고 싶은 안드로이드 개발자

0개의 댓글