뷰 결합

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

대부분의 경우 뷰 결합이 findViewById를 대체합니다.

설정 안내

뷰 결합은 모듈별로 사용 설정됩니다. 모듈에서 뷰 결합을 사용 설정하려면 다음 예와 같이 viewBinding 요소를 build.gradle 파일에 복사합니다.

android {
        ...
        viewBinding {
            enabled = true
        }
    }
    

결합 클래스를 생성하는 동안 레이아웃 파일을 무시하려면 tools:viewBindingIgnore="true" 속성을 레이아웃 파일의 루트 뷰에 추가하세요.

<LinearLayout
            ...
            tools:viewBindingIgnore="true" >
        ...
    </LinearLayout>
    

사용

모듈에 뷰 결합을 사용하도록 설정되면 모듈에 포함된 각 XML 레이아웃 파일의 결합 클래스가 생성됩니다. 각 결합 클래스에는 루트 뷰 및 ID가 있는 모든 뷰의 참조가 포함됩니다. 결합 클래스의 이름은 XML 파일의 이름을 카멜 표기법으로 변환하고 끝에 'Binding'을 추가하여 생성됩니다.

예를 들어 레이아웃 파일 이름이 result_profile.xml인 경우 다음과 같습니다.

<LinearLayout ... >
        <TextView android:id="@+id/name" />
        <ImageView android:cropToPadding="true" />
        <Button android:id="@+id/button"
            android:background="@drawable/rounded_button" />
    </LinearLayout>
    

생성된 결합 클래스 이름은 ResultProfileBinding이 됩니다. 이 클래스에는 name이라는 TextViewbutton이라는 Button 등 두 필드가 있습니다. 레이아웃의 ImageView에는 ID가 없으므로 결합 클래스에 참조가 없습니다.

또한 모든 결합 클래스에는 상응하는 레이아웃 파일의 루트 뷰에 관한 직접 참조를 제공하는 getRoot() 메서드가 포함됩니다. 이 예에서는 ResultProfileBinding 클래스의 getRoot() 메서드가 LinearLayout 루트 뷰를 반환합니다.

다음 섹션에서는 생성된 결합 클래스를 활동 및 프래그먼트에서 사용하는 방법을 보여줍니다.

활동에서 뷰 결합 사용

활동에 사용할 결합 클래스 인스턴스를 설정하려면 활동의 onCreate() 메서드에서 다음 단계를 따릅니다.

  1. 생성된 결합 클래스에 포함된 정적 inflate() 메서드를 호출합니다. 그러면 활동에서 사용할 결합 클래스 인스턴스가 생성됩니다.
  2. getRoot() 메서드를 호출하거나 Kotlin 속성 구문을 사용하여 루트 뷰 참조를 가져옵니다.
  3. 루트 뷰를 setContentView()에 전달하여 화면상의 활성 뷰로 만듭니다.

Kotlin

    private lateinit var binding: ResultProfileBinding

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        binding = ResultProfileBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)
    }
    

자바

    private ResultProfileBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ResultProfileBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
    }
    

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

Kotlin

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

자바

    binding.getName().setText(viewModel.getName());
    binding.button.setOnClickListener(new View.OnClickListener() {
        viewModel.userClicked()
    });
    

프래그먼트에서 뷰 결합 사용

프래그먼트에 사용할 결합 클래스 인스턴스를 설정하려면 프래그먼트의 onCreateView() 메서드에서 다음 단계를 따릅니다.

  1. 생성된 결합 클래스에 포함된 정적 inflate() 메서드를 호출합니다. 그러면 프래그먼트에서 사용할 결합 클래스 인스턴스가 생성됩니다.
  2. getRoot() 메서드를 호출하거나 Kotlin 속성 구문을 사용하여 루트 뷰 참조를 가져옵니다.
  3. onCreateView() 메서드에서 루트 뷰를 반환하여 화면상의 활성 뷰로 만듭니다.

Kotlin

    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
    }
    

자바

    private ResultProfileBinding binding;

    @Override
    public View onCreateView (LayoutInflater inflater,
                              ViewGroup container,
                              Bundle savedInstanceState) {
        binding = ResultProfileBinding.inflate(inflater, container, false);
        View view = binding.getRoot();
        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
    

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

Kotlin

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

자바

    binding.getName().setText(viewModel.getName());
    binding.button.setOnClickListener(new View.OnClickListener() {
        viewModel.userClicked()
    });
    

findViewById와의 차이점

뷰 결합에는 findViewById를 사용하는 것에 비해 다음과 같은 중요한 장점이 있습니다.

  • Null 안전: 뷰 결합은 뷰의 직접 참조를 생성하므로 유효하지 않은 뷰 ID로 인해 null 포인터 예외가 발생할 위험이 없습니다. 또한 레이아웃의 일부 구성에만 뷰가 있는 경우 결합 클래스에서 참조를 포함하는 필드가 @Nullable로 표시됩니다.
  • 유형 안전: 각 바인딩 클래스에 있는 필드의 유형이 XML 파일에서 참조하는 뷰와 일치합니다. 즉, 클래스 변환 예외가 발생할 위험이 없습니다.

이러한 차이점은 레이아웃과 코드 사이의 비호환성으로 인해 런타임이 아닌 컴파일 시간에 빌드가 실패하게 된다는 것을 의미합니다.

데이터 결합과 비교

뷰 결합과 데이터 결합은 모두 뷰를 직접 참조하는 데 사용할 수 있는 결합 클래스를 생성합니다. 하지만 뷰 결합은 보다 단순한 사용 사례를 처리하기 위한 것이며 데이터 결합에 비해 다음과 같은 이점을 제공합니다.

  • 더 빠른 컴파일: 뷰 결합에는 주석 처리가 필요하지 않으므로 컴파일 시간이 더 짧습니다.
  • 사용 편의성: 뷰 결합에는 특별히 태그된 XML 레이아웃 파일이 필요하지 않으므로 앱에서 더 신속하게 채택할 수 있습니다. 모듈에서 뷰 결합을 사용 설정하면 모듈의 모든 레이아웃에 뷰 결합이 자동으로 적용됩니다.

반대로 뷰 결합에는 데이터 결합과 비교할 때 다음과 같은 제한사항이 있습니다.

위 사항을 고려할 때 일부 사례에서 프로젝트에 뷰 결합과 데이터 결합을 모두 사용하는 것이 가장 좋습니다. 고급 기능이 필요한 레이아웃에는 데이터 결합을, 고급 기능이 필요 없는 레이아웃에는 뷰 결합을 사용할 수 있습니다.