본문 바로가기
Mobile App

[안드로이드] - Fragment에서 ViewBinding 사용 (_binding 언더바 사용하는 이유)

by Jman 2022. 7. 26.

Fragment (프래그먼트)

프래그먼트는 FragmentActivity 내의 어떤 동작 또는 사용자 인터페이스의 일부를 나타낸다.

또한, 프래그먼트는 액티비티의 모듈식 섹션이라고 생각하면 된다.

이는 자체적인 수명 주기를 가지고, 자체 입력 이벤트를 수신하고, 액티비티 실행 중에 추가 및 삭제가 가능하다.

 

프래그먼트는 항상 액티비티 내에서 호스팅되어야 하며, 해당 프래그먼트의 수명 주기는 호스트 액티비티의 수명 주기에 직접적으로 영향을 받는다.

ex. 액티비티가 일시정지되는 경우, 그 안의 모든 프래그먼트도 일시정지되며 액티비티가 소멸되면 모든 프래그먼트도 모두 소멸.

 

프래그먼트는 액티비티와 다르게 조금은 다른 생명주기를 가지고 있다.

프래그먼트의 고유한 생명 주기를 가지고 있으면서, View 와 관련된 생명 주기도 가지고 있다.

 

즉, 2개의 라이프 사이클이 존재한다.

 

  • Fragment LifeCycle
  • Fragment View LifeCycle

 

 

https://developer.android.com/guide/components/fragments?hl=ko

 

위의 그림을 보면 프래그먼트 수명 주기 처리를 그림으로 나타내 있다.

프래그먼트 콜백 쪽 보면, onCreateView()onCreate() 두 가지의 생명 주기가 있는 걸 볼 수 있다.

 

onCrate() : 프래그먼트가 생성될 때, 즉 화면이 아직 보이지 않는 상태에서 실행 됨.

=>   ex. Fragment LifeCycle : onAttach() ~ onDetach()

 

onCreateView : 화면을 구성할 때 호출되는 부분

=>   ex. Fragment View LifeCycle : onCreateView() ~ onDestroyView()

 

따라서, 직접적으로 화면과 관련된 생명주기는 OnCreateView() 와 onDestroyView 이다.

 

 

Fragment 의 재사용

프래그먼트는 재사용을 대비해서 프래그먼트의 View 들을 메모리에 보관하도록 되어있다.

추가로 설명하면, 프래그먼트 A에서 B로 화면이 바뀌게될 때, 프래그먼트 A의 모든 View 요소들은 제거가된다.

하지만, 프래그먼트의 instance는 그대로 남아서 backStack에 저장될 것이다.

ex.) 프래그먼트에 네비게이션 컴포넌트, 백스택 또는 디테치를 사용할 경우, onDestroyView() 이후에 Fragemnt View 는 종료되지만, Fragment 는 여전히 살아있다.

다시 말해서,

프래그먼트의 onDestroy() 호출되고 나면 프래그먼트에 대한 참조는 더 이상 존재하지 않지만내부적으로 View들을 재사용하기 위해 보관하게 된다는 것이다.

여기서 메모리 릭의 가능성이 생긴다.

 

Fragment 에서 메모리 누수 방지

아래 코드는 구글 문서에 나온 예제입니다.

        private var _binding: ResultProfileBinding? = null
        // This property is only valid between onCreateView and
        // onDestroyView.
        private val binding get() = _binding!!

        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
       	// inflate() 메서드 호출 : Fragment 에서 사용할 결합 클래스 인스턴스 생성이 됨.
            _binding = ResultProfileBinding.inflate(inflater, container, false)
            val view = binding.root // 루트 뷰 참조 가져오기
            return view
        }

        override fun onDestroyView() {
            super.onDestroyView()
            _binding = null
        }

위 코드를 보게되면, onDestroyView() 가 호출될 시, _binding 객체를 null 처리를 해준 걸 확인할 수 있다.

저 코드는 ViewBinding 에 대한 참조를 가비지 컬렉터가 가비지 컬렉션을 할 수 있도록 하는 코드이다.

 

그리고 기존 액티비티 코드처럼 단순하게 lateinit 으로 선언했다면 onDestroyView 에서 binding을 null로 초기화할 수가 없다.

따라서, _binding을 선언한 후, nullable 처리를 해줬고, binding 프로퍼티에 가져올 때 null 일 경우 예외를 발생시키기 위해 예외 연선자 (!!)를 사용한 코드다.

 

이제 결합 클래스 인스턴스를 사용하여 뷰를 참조할 수 있다.

    binding.name.text = viewModel.name
    binding.button.setOnClickListener { viewModel.userClicked() }

 

 

참고

https://developer.android.com/topic/libraries/view-binding?hl=ko 

 

뷰 결합  |  Android 개발자  |  Android Developers

뷰 결합 뷰 결합 기능을 사용하면 뷰와 상호작용하는 코드를 쉽게 작성할 수 있습니다. 모듈에서 사용 설정된 뷰 결합은 모듈에 있는 각 XML 레이아웃 파일의 결합 클래스를 생성합니다. 바인딩

developer.android.com

https://developer.android.com/guide/components/fragments?hl=ko 

 

프래그먼트  |  Android 개발자  |  Android Developers

A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section

developer.android.com

https://gift123.tistory.com/58

 

안드로이드 개발 (29) Fragment에서 ViewBinding 사용 시 주의할 점

1. ViewBinding ViewBinding 은 xml를 자동으로 바인딩 클래스로 생성해서 xml의 View를 안전하게 사용할 수 있습니다. kotlin extension deprecated 이 되고나서 요즘은 ViewBinding, DataBinding을 위주로 사용..

gift123.tistory.com

https://yoon-dailylife.tistory.com/57

 

Android) Fragment에서 View Binding 문제점, 제대로 사용하기

View Binding을 모르시는 분들은 이전 글에서 확인 부탁드립니다. Problems in ViewBinding View Binding in Fragment private var _binding: ResultProfileBinding? = null // This property is only valid betw..

yoon-dailylife.tistory.com