class SearchFragment : Fragment(R.layout.fragment_search) {
private var _binding: FragmentSearchBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentSearchBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
// ...
}
위의 코드를 보면 Fragment의 생성자로 layoutId를 넘겨주고 있다.
습관적으로 이렇게 사용해왔는데 이걸 왜 사용해야 하는지 모르고 사용하다 보니, 잘못 사용하고 있다는 것을 알게 되었다.
Fragment(R.layout.fragment_search)의 내부 코드를 보면 이렇다.
//... (설명 주석 생략)
@ContentView
public Fragment(@LayoutRes int contentLayoutId) {
this();
mContentLayoutId = contentLayoutId;
}
주석 설명에 따르면 이것은 Fragment의 Alternate constructor(대체 생성자)로 onCreateView()에 의해 inflate될 레이아웃을 제공하기 위함이 목적이다. 위 코드의 mContentLayoutId는 Fragment class의 프로퍼티인데, 이 프로퍼티를 우리가 넘겨준 contentLayoutId 생성자 파라미터로 초기화하고 있다.
//... (설명 주석 생략)
@MainThread
@Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
if (mContentLayoutId != 0) {
return inflater.inflate(mContentLayoutId, container, false);
}
return null;
}
mContentLayoutId가 어디서 사용되는지 살펴보면, onCreateView()메소드에서 레이아웃을 inflate하는데 사용되고 있다. 즉, Alternate constructor로 contentLayoutId를 넘겨주면, mContentLayoutId != 0 조건이 true이므로, inflate가 자동으로 이루어진다. 그래서 개발자가 직접 onCreateView()를 override하여 또다시 레이아웃을 inflate해 줄 필요가 없다.
// 1차 수정 후
class SearchFragment : Fragment(R.layout.fragment_search) {
private var binding: FragmentSearchBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//...
}
//...
}
수정한 코드는 위와 같다.
하지만 이렇게 되면 binding 객체는 계속 null을 유지하게 된다. binding 객체를 통해서 레이아웃의 View에 접근해야 하는데 이렇게 되면 접근할 수가 없다. bind() 메소드를 사용하여 이를 해결할 수 있다.

위와 같이, 안드로이드 공식문서에서도 이미 layout이 inflate 되었다면 bind() 메소드를 대신 호출할 수 있다고 설명하고 있다.
// 2차 수정 후
class SearchFragment : Fragment(R.layout.fragment_search) {
private var binding: FragmentSearchBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentSearchBinding.bind(view)
}
//...
}
https://developer.android.com/topic/libraries/view-binding#fragments
https://github.com/android/architecture-components-samples/blob/master/ViewBindingSample/app/src/main/java/com/android/example/viewbindingsample/BindFragment.kt#L36-L41