티스토리 뷰
[Android] View Binding, Activity에서와 Fragment에서 왜 구현 방법이 다를까?
weekyear 2021. 4. 17. 23:53안드로이드 개발을 할 때, Activity나 Fragment에서 레이아웃 xml에서 textView나 Button을 가져오기 위해 findViewById 코드를 지겹게 작성해보았을 것입니다.
이런 코드를 줄여보고자 kotlin에서는 kotlin-android-extenstions를 사용하기도 하지만 요즘은 view binding을 사용하는 추세로 가는 듯 합니다.
그래서 필자도 view binding을 활용하고자 아래 공식 문서의 참조 코드를 보면서 코드를 작성하고 있는데 문득 이런 생각이 들었습니다.
- Fragment에서는 왜 OnDestroyView에서 binding을 다시 null로 바꿔주는 코드를 추가해줄까?
- Activity에서와 Fragment에서 선언하는 binding 변수 개수가 왜 다를까?
우선 Activity와 Fragment의 참조 코드는 다음과 같다.
View Binding in Activity
private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
View Binding in 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? {
_binding = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
두 가지 질문에 대한 답은 사실 하나로 귀결됩니다. 공식 문서에도 해당 문제에 대한 답이 나와 있습니다.
좀 더 풀어서 설명하자면 구글은 Fragment의 뷰들보다 오래 지속되고 다른 뷰들과 함께 재사용되도록 Fragment의 동작을 변경하였습니다.
그래서 onDestroy() - onDestroyView()가 호출된 후에 ViewBinding에 대한 레퍼런스를 가비지 컬렉터가 가비지 컬렉션을 할 수 있도록 명확하게 해줄 필요가 생겨 onDestroyView에서 _binding 변수를 null로 처리해줬습니다.
그리고 기존의 Activity의 코드처럼 단순하게 lateinit으로 선언한다면 onDestroyView에서 binding을 null 값으로 초기화할 수 없습니다. 그래서 _binding을 선언한 후 nullable(?) 처리를 해줬고 binding 프로퍼티에서 가져올 때 null일 경우 예외를 발생시키기 위해 예외발생 연산자(!!)를 사용하였습니다.
결론 : 이유없이 쓰여진 코드는 없다!
참조