Android

[Android] Fragment의 정의와 필요성, Lifecycle 및 이에 따른 대응.

pupu_2 2023. 6. 25. 14:30

 

 

 

 

Intro..

저번 포스팅에 이어 Fragment Lifecycle을 다뤄보려 한다. 

프레그먼트란 무엇인지, lifecycle, 대응사항(중요) 순으로 작성해보겠다!

 

 


 

 

 

Fragment 란?

이름 뜻 그대로 조각이다. 

Activity 위에서만 동작하는 화면이라 생각하면 편하다.

 

 

대신, Activity와 마찬가지로 코드, 레이아웃 xml을 작성할 수 있고, 

한 Activity 위에 하나 이상의 Fragment 조각이 존재할 수 있다.

 

 

뭔가 들어보면 Activity가 할 수 있는 기능인데 굳이 필요한가?? 라고 생각할 수 있지만, 

거의 대부분의 프로젝트에서 Fragment를 써먹는걸 보면 필요하니까 쓰는것같다.. 이유가 뭘까??

 

 

첫번째로, 가볍기 때문이다. 

Activity의 경우 Fragment에 비해 무겁고, 초기화 시간도 많이걸린다. 

Framgnet는 더 가볍기 때문에 메모리 효율도 좋다. 가볍기 때문에 Fragment 전환 시 비교적 빠르다.

 

 

두번째로, 데이터 공유측면에서 유리하기 때문이다. 

일반적으로 여러 Activity는 각각의 프로세스에서 실행되고 있고, 

(시스템 관리 중 필요에 따라 달라질 수 있으며) 

프로세스는 각각의 메모리를 할당받아 관리되기 때문에, 프로세스간 데이터를 주고받으려면 Intent 라는 객체를 사용해야 한다. 

따라서 이러한 방식은 직접 접근하는 방식보다 느릴 수 밖에 없다. 

그러나, Fragment는 하나의 프로세스 안에 존재하기 때문에 직접 접근이 가능하여 빠르고 유리하다.

 

 

세번째로, 관리가 쉽다. 

하나의 Activity에 여러 기능이 필요할 경우 Activity 클레스내에 수십에서 수백줄의 코드가 요구된다. 

그러나 하나의 Activity 에 여러 Fragment 를 배치할 경우, 기능별로 코드를 분담해 담을 수 있으며 이는 가독성 및 코드 재사용성이 올라가고 관심사를 분리시켜 의존성을 줄이고 독립성을 키우게 된다. 

추가적으로, 모든 Fragment는 (부모)Activity의 생명주기를 따라가기 때문에, 

맘에 안들어 Activity를 초기화 시키면, 그 위에있는 프레그먼트들이 몽땅 따라서 초기화된다. 훨씬 관리가 쉽다.

 

 

그렇다면 단점은? 비동기 문제가 발생할 수 있고, Activity의 생명주기를 고려하며 Fragment 생명주기를 고려해야하기 때문에 복잡하다.

 

 

 


 

Fragment Lifecycle

프래그먼트는 왼쪽 사진과 같이 정해진 생명주기에 따라 움직인다. (같은사진입니다)

 

onAttact

  • 나와있진 않지만 가장 먼저 진행되는 단계다.
  • 프래그먼트가 호스트 액티비티에 attach되는 단계.

onCreate

  • Fragment가 생성된 단계 / FragmentManager에 의해 add 됐을때 도달하는 단계.
  • View가 생성되지 않았기에 View관련 작업 두기에는
    부적절 
  • onSaveInstanceState 
  • 세로, 가로 모드 변환 시에도 onCreate 함수가 호출됨.
    이때 프래그먼트가 초기화 됨에 따라 값들이 전부 초기화되기 때문에, 값을 유지하고싶을 경우 savedInstanceState 를 활용할 수 있음.
    (화면 회전시에 호출되는 오버라이드 함수임)
     그치만 이 기능은 Bitmap이나 대량 데이터에는 적합하지 않고, 적은 데이터에 적합 

onCreateView

  • view를 inflater하여 초기화, 생성하는 단계.

onViewCreated

  • 완전한 View 생성을 보장해주는 단계.
  • onCreateView에서 정상적으로 View 객체가 반환됐을 때 도달하는 단계로, View 초기값 설정, 리스너 설정, LiveData 옵저빙, RecyclerView나 ViewPager2에 사용될 adapter 세팅 등을 이곳에서 하는것이 더 안전함.

onViewStateRestored

  • 저장해둔 상태 값등을 불러옴
  • View lifecycle owner는 이때 initlalized에서 Created로 변환해줌

onStart

  • Fragment가 사용자에게 보여질 수 있을 때 호출
  • Fragment의 child FragmentManager를 통해 FragmentTransaction을 안전 수행
  • View lifecycle owner는 이때 STARTED로 변환해줌

onResume

  • Fragment가 보이는 상태에서 Animator, Transition 효과가 종료되고, 프래그먼트와 사용자가 상호작용할 수 있을 때 호출되는 단계.
  • 즉 사용자와 프래그먼트가 상호작용하기 적절한 상태.
  • 반대로 이 단계에가 아니라면 입력 시도나 포커스 설정등을 하면 안된다는것을 의미

onPause

  • 사용자가 Fragment 를 떠나기 시작했으나 Fragment는 여전히 Visible일 때 호출되는 단계

onStop

  • 더이상 화면에 보여지지 않는 단계
  • 부모 액티비티나 프래그먼트가 중단 or 상태 저장할때 호출됨
  • 여기까지 Fragment Transaction을 안전히 수행할 수 있는 마지막 지점

onSaveInstanceState

  • 값을 저장하는 곳
  • 화면의 회전, home 버튼을 눌러 밖으로 나간경우에 호출됨

onDestroyView

  • 모든 exit animation, transition이 완료되고 Fragment가 화면으로부터 벗어났을 경우 호출
  • 이 시점에서는 가비지 컬렉터에 의해 수거될 수 있도록 Fragment View에 대한 모든 참조가 제거되어야 함 (메모리누수)

onDestroy

  • Fragment 가 제거되거나, FragmentManager 가 destory 됐을 때 해당 함수 호출.

onDetach

  • 가장 마지막 단계

 

 

 

 

 

 

 


Fragment Lifecycle 에 따른 고려사항 (중요!)

 

case 1 : First Fragment 위에 Seconde fragment가 올라가는(Add) 경우.

First Fragment가 onResume 된 상태에서 새 프래그먼트가 올라감

 

 

 

case 2 : First Fragment 에서 third fragment로 바뀌는 (replace) 경우. (addToBackStack : true)

Frist Fragment 가 onResume 상태에서 secondeFragment를 replace 함수 호출 후,

First onPause → stop까지 진행,

Seconde가 onstart 까지 진행

first 의 onDestroyView 가 호출된 후, seconde onResume 실행되며 대기.

 

 

 

case 3 : First Fragment 에서 seconde fragment로 replace 하는 경우. (addToBackStack : false)

case 2와 같지만, First의 onDestroyView, onDestory, onDetach까지 진행된 후

seconde onResume 됨

 

 

 

case 4 : home 버튼을 눌러 빠져나간경우

onResume 까지 동작된 후,

onPause, onStop, onSaveInstanceState 까지 간 후 대기함

만약 휴대폰 메모리가 부족할 경우 detroy될수도있음

 

 

 

case 5 : ViewBinding을 사용한 경우

Fragment 전환 시, Add나 Replace Back Stack 인 경우

사용된 ViewBinding 또한 메모리에 올라가있는 상태로 Back Stack에 들어간다.

이는 분명한 메모리 누수이기 때문에 binding을 null로 비워줘야 한다.

 

 

 

 

 

 

 

 

 

학부생 레벨에서 쓴 글로, 다소 부족한 부분이 있을 수 있으니 친절한 피드백을 매우 환영합니다.