생성된 결합 클래스

데이터 결합 라이브러리는 레이아웃의 변수 및 뷰에 액세스하는 데 사용되는 결합 클래스를 생성합니다. 이 페이지에서는 생성된 결합 클래스를 만들고 맞춤설정하는 방법을 보여줍니다.

생성된 결합 클래스는 레이아웃 변수를 레이아웃 내의 뷰와 연결합니다. 결합 클래스의 이름 및 패키지는 맞춤설정할 수 있습니다. 생성된 모든 결합 클래스는 ViewDataBinding 클래스에서 상속됩니다.

각 레이아웃 파일의 결합 클래스가 생성됩니다. 기본적으로 클래스 이름은 레이아웃 파일 이름을 기반으로 하여 파스칼 표기법으로 변환하고 Binding 접미사를 추가합니다. 위의 레이아웃 파일 이름은 activity_main.xml이므로 생성되는 클래스는 ActivityMainBinding입니다. 이 클래스는 레이아웃 속성(예: user 변수)에서 레이아웃 뷰까지 모든 결합을 보유하며 결합 표현식에 값을 할당하는 방법도 인식합니다.

결합 객체 만들기

레이아웃 내에서 표현식을 통해 뷰에 결합되기 전에는 뷰 계층 구조가 수정되지 않도록 하기 위해, 레이아웃 확장 후에 바로 결합 객체가 생성됩니다. 객체를 레이아웃에 결합하는 가장 일반적인 방법은 결합 클래스에서 정적 메서드를 사용하는 것입니다. 다음 예에 나와 있는 것처럼, 결합 클래스의 inflate() 메서드를 사용하여 뷰 계층 구조를 확장하고 객체를 뷰 계층 구조에 결합할 수 있습니다.

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)

        setContentView(binding.root)
    }

    

자바

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater());

        setContentView(binding.root);
    }

    

다음 예에서와 같이 LayoutInflater 객체 외에도 ViewGroup 객체를 사용하는 inflate() 메서드의 대체 버전이 있습니다.

Kotlin

    val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)

    

자바

    MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);

    

레이아웃이 다른 메커니즘을 사용하여 확장되었다면 다음과 같이 별도로 결합될 수 있습니다.

Kotlin

    val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

    

자바

    MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

    

결합 유형을 미리 알 수 없는 상황도 있습니다. 그런 상황에서는 다음 코드 스니펫에서와 같이 DataBindingUtil 클래스를 사용하여 결합을 생성할 수 있습니다.

Kotlin

    val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent)
    val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)

    

자바

    View viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent);
    ViewDataBinding binding = DataBindingUtil.bind(viewRoot);

    

Fragment, ListView 또는 RecyclerView 어댑터에서 데이터 결합 항목을 사용하고 있다면, 다음 코드 예에서와 같이 결합 클래스 또는 DataBindingUtil 클래스의 inflate() 메서드를 사용할 수도 있습니다.

Kotlin

    val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
    // or
    val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)

    

자바

    ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
    // or
    ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

    

ID가 있는 뷰

데이터 결합 라이브러리는 레이아웃에 ID가 있는 각 뷰의 결합 클래스에 불변 필드를 생성합니다. 예를 들어 데이터 결합 라이브러리는 다음 레이아웃에서 TextView 유형의 firstNamelastName 필드를 생성합니다.

<layout xmlns:android="http://schemas.android.com/apk/res/android">
       <data>
           <variable name="user" type="com.example.User"/>
       </data>
       <LinearLayout
           android:orientation="vertical"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.firstName}"
       android:id="@+id/firstName"/>
           <TextView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="@{user.lastName}"
      android:id="@+id/lastName"/>
       </LinearLayout>
    </layout>
    

라이브러리는 단일 패스로 뷰 계층 구조에서 ID가 포함된 뷰를 추출합니다. 이 메커니즘은 레이아웃의 모든 뷰에 findViewById() 메서드를 호출하는 것보다 속도가 더 빠를 수 있습니다.

ID는 데이터 결합이 없을 때만큼 필요하지는 않지만 코드에서 계속 뷰에 액세스해야 하는 상황이 여전히 있습니다.

변수

데이터 결합 라이브러리는 레이아웃에 선언된 각 변수의 접근자 메서드를 생성합니다. 예를 들어, 다음 레이아웃은 user, image, note 변수의 결합 클래스에 setter 및 getter 메서드를 생성합니다.

<data>
       <import type="android.graphics.drawable.Drawable"/>
       <variable name="user" type="com.example.User"/>
       <variable name="image" type="Drawable"/>
       <variable name="note" type="String"/>
    </data>
    

ViewStub

일반 뷰와 달리 ViewStub 객체는 보이지 않는 뷰로 시작됩니다. 이 객체는 가시적으로 표시되거나 확장을 명시적으로 지시받으면 또 다른 레이아웃을 확장함으로써 레이아웃의 자체 뷰를 대체합니다.

ViewStub이 기본적으로 뷰 계층 구조에서 사라지기 때문에 가비지 컬렉션을 통한 메모리 회수가 가능하도록 결합 객체의 뷰도 사라져야 합니다. 뷰가 최종적이므로 ViewStubProxy 객체는 생성된 결합 클래스에서 ViewStub를 대체하며, 이에 따라 개발자는 ViewStub가 존재할 경우 이에 액세스할 수 있고 ViewStub가 확장된 경우 확장된 뷰 계층 구조에도 액세스할 수 있습니다.

또 다른 레이아웃을 확장할 때 새 레이아웃의 결합을 설정해야 합니다. 따라서 ViewStubProxyViewStub OnInflateListener를 수신 대기하고 필요할 때 결합을 설정해야 합니다. 지정된 시간에 하나의 리스너만 존재할 수 있으므로 ViewStubProxy를 통해 OnInflateListener를 설정할 수 있습니다. 설정된 이 리스너는 결합을 설정하면 호출됩니다.

즉시 결합

변수 또는 관찰 가능한 객체가 변경될 때 결합은 다음 프레임 이전에 변경되도록 예약됩니다. 하지만 결합이 즉시 실행되어야 하는 때도 있습니다. 이럴 때 강제로 실행하려면 executePendingBindings() 메서드를 사용하세요.

고급 결합

동적 변수

구체적인 결합 클래스를 알 수 없는 때도 있습니다. 예를 들어 임의의 레이아웃에 작동하는 RecyclerView.Adapter는 특정 결합 클래스를 인식하지 못합니다. 따라서 이 어댑터는 onBindViewHolder() 메서드를 호출하는 동안에도 계속해서 결합 값을 할당해야 합니다.

다음 예에서는 RecyclerView가 결합되는 모든 레이아웃에 item 변수가 있습니다. BindingHolder 객체에는 ViewDataBinding 기본 클래스를 반환하는 getBinding() 메서드가 있습니다.

Kotlin

    override fun onBindViewHolder(holder: BindingHolder, position: Int) {
        item: T = items.get(position)
        holder.binding.setVariable(BR.item, item);
        holder.binding.executePendingBindings();
    }

    

자바

    public void onBindViewHolder(BindingHolder holder, int position) {
        final T item = items.get(position);
        holder.getBinding().setVariable(BR.item, item);
        holder.getBinding().executePendingBindings();
    }

    

백그라운드 스레드

컬렉션이 아닌 한 백그라운드 스레드에서 데이터 모델을 변경할 수 있습니다. 데이터 결합은 계산 중에 각 변수/필드를 현지화하여 동시 실행 문제를 방지합니다.

맞춤 결합 클래스 이름

기본적으로 결합 클래스는 레이아웃 파일 이름을 기반으로 하여 대문자로 시작하고 밑줄(_)을 삭제하며 다음 문자를 대문자로 표기하고 Binding이라는 단어를 접미사로 추가하는 방법으로 생성됩니다. 이 클래스는 모듈 패키지 아래의 databinding 패키지에 배치됩니다. 예를 들어 레이아웃 파일 contact_item.xmlContactItemBinding 클래스를 생성합니다. 모듈 패키지가 com.example.my.app이면 결합 클래스가 com.example.my.app.databinding 패키지에 배치됩니다.

data 요소의 class 속성을 조정하여 결합 클래스의 이름을 바꾸거나 결합 클래스를 다른 패키지에 배치할 수도 있습니다. 예를 들어 다음 레이아웃은 현재 모듈의 databinding 패키지에 ContactItem 결합 클래스를 생성합니다.

<data class="ContactItem">
        …
    </data>
    

클래스 이름 앞에 마침표를 접두사로 추가하여 다른 패키지에서 결합 클래스를 생성할 수 있습니다. 다음 예는 모듈 패키지에 결합 클래스를 생성합니다.

<data class=".ContactItem">
        …
    </data>
    

또한 결합 클래스를 생성할 패키지의 전체 이름을 사용할 수도 있습니다. 다음은 com.example 패키지에 ContactItem 결합 클래스를 만드는 예입니다.

<data class="com.example.ContactItem">
        …
    </data>
    

추가 리소스

데이터 결합에 관해 자세히 알아보려면 다음 추가 리소스를 참조하세요.

샘플

Codelab

블로그 게시물