오늘도 더 나은 코드를 작성하였습니까?

DataBinding 이벤트 처리하기 본문

Android Jetpack Architecture/DataBinding

DataBinding 이벤트 처리하기

hik14 2020. 8. 7. 17:02

데이터 바인딩은 onClick() 메서드 등과 같은 이벤트를 뷰로 가져와서 처리할 수 있는 기능을 제공합니다.

이벤트 속성 이름은 리스너 메소드의 이름을 따른다. 예를 들어 OnClickListener를 구현 시 OnClick()을 작성해야 된다.

 

이벤트 속성의 이름은 adroid:onClick() = "  " 이 된다.

Button button;
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
            }
        });
	<Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick=""/>

 

데이터 바인딩에서는 이벤트를 다루는 방법에는 2가지가 있다.

 

두 방법의 가장 큰 차이점은 데이터의 바인딩이 일어날 때 실제 리스너의 생성을 하느냐 안 하느냐 이다.

 

메서드 참조 방식

바인딩 표현식에서 리스너 메서드의 시그니처(메소드 이름, 매개변수 개수 및 타입)을 따라 참조를 하는 방식이다. 바인딩 표현식에서 메소드 참조를 사용하려면 데이터 바인딩은 메서드를 가진 객체를 감싸는 리스너를 생성하여 대상 뷰의 리스너로 설정한다. 만약 바인딩 표현식이 null 이면 리스너를 생성하지 않고 리스너를 null로 설정한다.

 

이벤트 핸들러 메소드를 직접적으로 바인딩한다.

 

메서드 시그니처가 정확하지 않은경우 컴파일 타임에 에러를 확인할수 있다.

반드시 메소드 참조로 바인딩 표현식에서 이벤트를 처리할 땐 해당 이벤트 처리 메서드의 시그니처와 동일해야 된다. 

public class EventHandlers {

    private static final String TAG = "EventHandlers";

    public void onClickTestButton(View view){
        Log.d(TAG, "onClickTestButton: 버튼이 눌렸다.");
    }

}
<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>
        <variable
            name="handlers"
            type="com.professionalandroid.apps.databinding.EventHandlers" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="test"
            android:onClick="@{handlers::onClickTestButton}"/>
    </LinearLayout>
</layout>

 

만약 onClickTestButton(View view , String str)로  시그니처를 안 맞춘다면, 컴파일 시 다음과 같은 에러가 난다.

 

 

리스너 바인딩 방식 

리스너 결합은 이벤트가 발생할 때 실행되는 결합 표현식입니다. 리스너 결합은 메서드 참조와 비슷합니다

람다 표현식에서는 이벤트가 발생할 때마다 해당 람다 표현식을 실행할지 결정한다. 

데이터 바인딩은 대상 객체의 null 여부와 관계없이 항상 리스너를 만들고 뷰에 리스너를 설정한다. 

 

 

리스너 바인딩에서는 단지 반환되는 타입만 이벤트 리스너의 반환 타입과 일치시킨다.

 

바인딩 표현식에서 콜백이 사용될 때 데이터 바인딩은 자동으로 필요한 리스너를 생성 후 뷰에 리스너를 설정한다.

뷰에서 실제로 이벤트가 발생하면 데이터 바인딩은 주어진 표현식을 평가한다. 

일반적으로 바인딩 표현식에서 이런 평가가 진행되는 동안 null과 스레드 안정성이 확보됩니다.

package com.professionalandroid.apps.databinding;

import android.util.Log;

public class Presenter {

    private static final String TAG = "Presenter";

    public void onSaveClick(User user){
        Log.d(TAG, "onSaveClick: "+user.toString());
    }

}
<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>
        <variable
            name="user"
            type="com.professionalandroid.apps.databinding.User"/>
        <variable
            name="presenter"
            type="com.professionalandroid.apps.databinding.Presenter" />
    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="test"
            android:onClick="@{() -> presenter.onSaveClick(user)}"/>
    </LinearLayout>
</layout>

 

위의 예제에서 중요한 건 onClick(View)에 제공할 view 매개변수를 정의하지 않았습니다.

 

리스너 바인딩은 두 가지 옵션을 제공하는데

 

1. 모든 매개 변수를 무시하고 사용하지 않는 것이다.

   

android:onClick="@{ ( ) -> presenter.onSaveClick(user)}"/>

 

2. 모든 매개변수의 이름을 정하고 바인딩 표현식에서 그것을 사용하는 것이다.

 

android:onClick="@{ (theView) -> presenter.onSaveClick(theView,  task)}"

 

아래 체크박스와 같은 경우 2개의 매개변수를 모두 지정했다. 

 

 

 

복잡한 리스너 방지

 

리스너 표현식은 매우 강력합니다. 리스너 표현식을 사용하면 코드를 매우 쉽게 읽을 수 있습니다.

반면에 복잡한 표현식이 포함된 리스너를 사용하면 레이아웃을 읽고 유지하기가 어려워집니다.

이러한 표현식은 사용 가능한 데이터를 UI에서 콜백 메서드로 전달하는 것만큼 간단해야 합니다.

리스너 표현식에서 호출한 콜백 메서드 내에 비즈니스 로직을 구현해야 합니다.

'Android Jetpack Architecture > DataBinding' 카테고리의 다른 글

DataBinding Component 사용하기  (0) 2020.08.07
DataBinding 자동객체 전환  (0) 2020.08.07
DataBinding 표현식 정리  (0) 2020.08.07
Binding Method BindingAdapter  (0) 2020.08.05
데이터 바인딩(DataBinding)  (0) 2020.08.05