[Android] Fragment의 생명주기(Life Cycle)과 onActivityCreated() deprecated 대응하기

2021. 12. 17. 20:07개발을 파헤치다/Android

반응형

 

Android 2020년 3월 18일 업데이트 이후 Fragment의 onActivityCreated가 지원 중단(deprecated)되었습니다.
기존의 onActivityCreated가 사라지고 새로운 메서드들이 생겼는데요.

기존 생명주기와 달라진 점이 무엇이고 onActivityCreated의 빈자리를 어떻게 채워야 하는지에 대해 살펴보겠습니다.

 

기존 생명주기(Life Cycle)와 달라진 점

 

기존 Fragment Life Cycle

먼저 기존 Fragment의 Life Cycle을 한번 보겠습니다. 아주 큰 변화는 아니지만 onActivityCreated가 지원 중단되고 3가지 새로운 메서드가 Life Cycle에 추가되었습니다.

새로운 Fragment의 Life Cycle



  • onViewCreated() : Fragment의 View(레이아웃)이 생성된 후의 호출됩니다. 이곳에서 View의 초기값을 설정하는 로직이 들어갑니다. 예를 들어, Live Data observing 코드, RecyclerView 혹은 ViewPager2에 사용할 Adapter 초기화는 등 말이죠.

  • onViewStateRestored() : 여기에서는 Fragment에 속하는 View들의 상태 값들을 모두 읽어왔을 때 호출됩니다. 예를 들어, 체크박스 위젯에 값이 체크가 되어있는지 등 각 View의 상태값들을 체크할 수 있습니다.

  • onSaveInstanceState() : Fragment의 상태 값(State)이 저장된 이후에 호출되는 메서드입니다. API 버전 28 이전에는 이 메서드가 호출되고 onStop()이 호출되었습니다. 따라서 onStop()에서도 이미 Fragment의 상태 값이 저장된 후였죠. 하지만 API 버전 28 이후에는 onStop()이 먼저 호출되고 이 메서드가 호출됩니다. 이때에는 onStop()에서 아직 상태가 저장되지 않은 상황입니다. 이 메서드가 호출되는 시점에서야 상태가 저장되게 됩니다.


기존 생명주기와 눈에 띄게 차이가 나는 부분은 역시 onActivityCreated 메서드가 사라진 점인데요. 이로써 Activity 생명주기와 Fragment 생명주기가 서로 영향을 덜 주고 깔끔하게 실행될 것 같습니다. 또, 기존에는 onActivityCreated에서 Fragment관련 초기화 루틴을 거의 실행했었는데 이를 어느 정도 분리한 것으로 보입니다. 공식 문서에 따르면 View 관련 초기화는 onViewCreated에서, 나머지 다른 초기화 루틴은 onCreate 메서드에서 수행하라고 나와있죠. 여기에 onActivityCreated의 존재 이유였던 Activity의 생성과 연관된 특정 Fragment 로직은 LifeCycleObserver를 통해 해결하라고도 나와있습니다. 확실히 구조가 더 깔끔해진 것 같네요. 개발자 입장에서는 좀 더 손이 가 긴 하지만요.

onActivityCreated 지원 중단 대응하기

가장 먼저, 왜 해당 메서드가 지원 중단되었는지부터 파악해봐야 할 것 같습니다. Android 공식 문서에는 아래와 같이 그 이유가 나와있는데요.


글의 내용을 확인해보면 onActivityCreated()가 탄생한 이유가 Activity의 생성이 끝나야만 처리되는 로직이 Fragment에 있을 때를 위한 것임을 알 수 있습니다. 확실히 앱을 개발하다 보면 이런 경우가 빈번히 발생할 수 있죠. 하지만 문제는 이 부분 때문에 Activity와 Fragment의 생명주기(Life Cycle)가 좀 더 단단하게 결합된다는 것이죠. 무슨 문제가 있을까 싶지만 커다란 Android 플랫폼을 지속적으로 확장 가능하고 깔끔한 구조를 유지해나가는 데에는 별로 좋지 않은 패턴이라고 볼 수 있습니다. 아마 그렇게 판단했기에 이 메서드를 지원 중단하기로 결정한 것이라 생각됩니다. 

그렇다면 Activity가 생성된 이후에 실행돼야 하는 Fragment 로직을 어떻게 처리하면 좋을까요?
공식 문서에서는 아래와 같은 얘기 합니다.



여기에서 onViewCreated의 역할을 확인할 수 있습니다. Fragment의 View와 관련된 로직을 이 메서드에서 처리하는 것이죠.
다른 초기화 코드는 onCreate()에서 처리하라고도 나와있습니다. Activity가 생성된 이후에 실행되어야 하는 로직은 LifeCycleObserver를 사용하라고 나와있는데요. 쉽게 얘기해서, 감시병을 세우는 거죠. LifeCycleObserver에게 Activity가 생성되는지 지켜보고 있다가 확인이 되면(이것을 Event가 발생한다고 얘기합니다.) Fragment에게 알려주는 것이죠. 이렇게하면 Activity의 생명주기와 단단히 결합되지 않으면서도 Fragment의 특정 로직을 처리할 수 있게됩니다. 이것을 코드로 구현하면 이렇습니다.

class HomeFragment: Fragment(), LifecycleObserver {

    lateinit var binding: FragmentHomeBinding

    // Fragment의 레이아웃을 생성한다
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_home,
            container,
            false
        )
        return binding.root
    }

    // Activity의 onCreate가 완료되고 실행할 Fragment 로직
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onActivityCreated(){
        // 여기에 특정 로직이 들어가면 된다
        val a = 10;
        // 더 이상 감시할 필요가 없으므로 Observer를 제거한다
        activity?.lifecycle?.removeObserver(this)
    }

    // Fragment의 생명주기 시작
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // Activity에 부착되는 순간 감시병(LifeCycleObserver)를 세워서 생성되는지 감시한다
        activity?.lifecycle?.addObserver(this)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // Fragment의 View관련 로직
        initView()
    }
}

이렇게 구현하면 Activity와 Fragment 각각 자신의 생명주기에 맞춰서 순차적으로 메서드들을 실행하다가 Activity의 onCreate가 되는 순간 annotation이 적용된 메서드가 실행됩니다. 위의 코드에서는 onActivityCreated() 메서드가 되겠네요. 이렇게 Activity의 생성 이후에 실행되어야하는 Fragment의 로직을 처리하면 됩니다.

 

 

반응형