결합 어댑터는 적절한 프레임워크를 호출하여
값을 설정할 수 있습니다. 한 가지 예는
setText()
메서드를 사용하여 지도 가장자리에
패딩을 추가할 수 있습니다. 다른
예를 들어 이벤트 리스너를 설정하는 것입니다.
setOnClickListener()
드림
메서드를 사용하여 축소하도록 요청합니다.
데이터 결합 라이브러리를 사용하면 값을 설정하기 위해 호출되는 메서드를 지정할 수 있습니다. 자체 바인딩 로직을 제공하고, 다음과 같이 반환된 객체의 유형을 어댑터 사용
속성 값 설정
바인딩된 값이 변경될 때마다 생성된 바인딩 클래스는 setter를 호출해야 합니다. 메서드를 호출할 수 있습니다. 데이터 결합이 라이브러리에서 자동으로 메서드를 결정하거나 개발자가 메서드를 사용하거나 커스텀 로직을 제공하여 메서드를 선택할 수 있습니다.
자동 메서드 선택
이름이 example
인 속성의 경우 라이브러리가 자동으로 메서드를 찾습니다.
호환되는 유형을 인수로 허용하는 setExample(arg)
입니다. 네임스페이스
속성이 고려되지 않습니다. 속성 이름과 유형만 사용됩니다.
을 사용하세요.
예를 들어 android:text="@{user.name}"
표현식이 있는 경우 라이브러리는
다음과 같이 반환된 유형을 허용하는 setText(arg)
메서드를 찾습니다.
user.getName()
입니다. user.getName()
의 반환 유형이 String
이면
라이브러리는 String
인수를 허용하는 setText()
메서드를 찾습니다. 만약
표현식이 int
을 반환하면 라이브러리는 setText()
메서드를
int
인수를 허용합니다. 표현식은 올바른 유형을 반환해야 합니다. 다음과 같은 작업을 할 수 있습니다.
필요한 경우 반환 값을 변환합니다.
지정된 이름의 속성이 없더라도 데이터 결합은 작동합니다. 다음과 같은 작업을 할 수 있습니다.
데이터 결합을 사용하여 setter에 대한 속성을 만들 수 있습니다. 예를 들어 지원 서비스는
클래스
DrawerLayout
드림
속성은 없지만 setter가 많습니다. 다음 레이아웃
자동으로
setScrimColor(int)
드림
및
addDrawerListener(DrawerListener)
app:scrimColor
및 app:drawerListener
의 setter인 메서드
다음과 같습니다.
<androidx.drawerlayout.widget.DrawerLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:scrimColor="@{@color/scrim}"
app:drawerListener="@{fragment.drawerListener}">
맞춤 메서드 이름 지정
일부 속성에는 이름이 일치하지 않는 setter가 있습니다. 이러한 상황에서는
속성은
BindingMethods
드림
주석을 추가합니다. 주석은 클래스와 함께 사용되며 여러 클래스를 포함할 수 있습니다.
BindingMethod
드림
주석을 추가합니다. 바인딩 메서드는
앱의 모든 클래스에 추가할 수 있습니다.
다음 예에서 android:tint
속성은
setImageTintList(ColorStateList)
메서드를 사용하세요. setTint()
메서드를 사용하지 않는 것이 좋습니다.
Kotlin
@BindingMethods(value = [ BindingMethod( type = android.widget.ImageView::class, attribute = "android:tint", method = "setImageTintList")])
자바
@BindingMethods({ @BindingMethod(type = "android.widget.ImageView", attribute = "android:tint", method = "setImageTintList"), })
일반적으로 Android 프레임워크 클래스에서 setter의 이름을 바꿀 필요는 없습니다. 이 속성은 이름 규칙을 사용하여 이미 구현되어 있으며 일치하는 메서드를 찾습니다.
맞춤 로직 제공
일부 속성에는 맞춤 결합 로직이 필요합니다. 예를 들어
android:paddingLeft
속성의 setter입니다. 대신 setPadding(left,
top, right, bottom)
메서드가 제공됩니다. 정적 결합 어댑터 메서드
BindingAdapter
주석을 사용하면 속성의 setter를 호출하는 방법을 맞춤설정할 수 있습니다.
Android 프레임워크 클래스의 속성에는 이미 BindingAdapter
가 있습니다.
주석을 달 수 있습니다. 다음 예는
paddingLeft
속성:
Kotlin
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, padding: Int) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) }
자바
@BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int padding) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); }
매개변수 유형은 중요합니다. 첫 번째 매개변수는 속성과 연결된 뷰를 반환합니다. 두 번째 매개변수는 지정된 속성에 대한 바인딩 식에서 허용되는 유형입니다.
결합 어댑터는 다른 유형의 맞춤설정에도 유용합니다. 예를 들어 커스텀 로더는 작업자 스레드에서 호출되어 이미지를 로드할 수 있습니다.
아래와 같이 여러 속성을 수신하는 어댑터도 있을 수 있습니다. 다음 예를 참고하세요.
Kotlin
@BindingAdapter("imageUrl", "error") fun loadImage(view: ImageView, url: String, error: Drawable) { Picasso.get().load(url).error(error).into(view) }
자바
@BindingAdapter({"imageUrl", "error"}) public static void loadImage(ImageView view, String url, Drawable error) { Picasso.get().load(url).error(error).into(view); }
다음 예와 같이 레이아웃에서 어댑터를 사용할 수 있습니다. 참고
@drawable/venueError
는 앱의 리소스를 나타냅니다. 주변
리소스를 @{}
로 설정하면 이를 유효한 결합 표현식으로 만듭니다.
<ImageView app:imageUrl="@{venue.imageUrl}" app:error="@{@drawable/venueError}" />
imageUrl
및 error
가 다음에 사용되는 경우 어댑터가 호출됩니다.
ImageView
객체에서 imageUrl
는
문자열이며 error
는
Drawable
원하는 경우
속성이 설정되었을 때 호출할 어댑터인 경우 선택적
requireAll
드림
어댑터의 플래그를 false
에 추가합니다.
Kotlin
@BindingAdapter(value = ["imageUrl", "placeholder"], requireAll = false) fun setImageUrl(imageView: ImageView, url: String?, placeHolder: Drawable?) { if (url == null) { imageView.setImageDrawable(placeholder); } else { MyImageLoader.loadInto(imageView, url, placeholder); } }
자바
@BindingAdapter(value={"imageUrl", "placeholder"}, requireAll=false) public static void setImageUrl(ImageView imageView, String url, Drawable placeHolder) { if (url == null) { imageView.setImageDrawable(placeholder); } else { MyImageLoader.loadInto(imageView, url, placeholder); } }
결합 어댑터 메서드는 핸들러의 이전 값을 사용할 수 있습니다. 메서드 기존 값과 새 값을 취하려면 먼저 속성에 대한 모든 기존 값을 선언해야 하며 다음 예와 같이 새 값이 뒤에 옵니다.
Kotlin
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, oldPadding: Int, newPadding: Int) { if (oldPadding != newPadding) { view.setPadding(newPadding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) } }
자바
@BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int oldPadding, int newPadding) { if (oldPadding != newPadding) { view.setPadding(newPadding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); } }
이벤트 핸들러는 인터페이스가 하나인 인터페이스 또는 추상 클래스에서만 추상 메서드를 지원합니다.
Kotlin
@BindingAdapter("android:onLayoutChange") fun setOnLayoutChangeListener( view: View, oldValue: View.OnLayoutChangeListener?, newValue: View.OnLayoutChangeListener? ) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (oldValue != null) { view.removeOnLayoutChangeListener(oldValue) } if (newValue != null) { view.addOnLayoutChangeListener(newValue) } } }
자바
@BindingAdapter("android:onLayoutChange") public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue, View.OnLayoutChangeListener newValue) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (oldValue != null) { view.removeOnLayoutChangeListener(oldValue); } if (newValue != null) { view.addOnLayoutChangeListener(newValue); } } }
다음과 같이 레이아웃에서 이 이벤트 핸들러를 사용할 수 있습니다.
<View android:onLayoutChange="@{() -> handler.layoutChanged()}"/>
리스너에 여러 메서드가 있으면 여러 리스너로 분할해야 합니다.
예를 들어
View.OnAttachStateChangeListener
드림
에는 두 가지 방법이 있습니다.
onViewAttachedToWindow(View)
및
onViewDetachedFromWindow(View)
:
라이브러리는 속성과 핸들러를 구별하는 두 개의 인터페이스를 제공합니다.
다음과 같습니다.
Kotlin
// Translation from provided interfaces in Java: @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) interface OnViewDetachedFromWindow { fun onViewDetachedFromWindow(v: View) } @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) interface OnViewAttachedToWindow { fun onViewAttachedToWindow(v: View) }
자바
@TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewDetachedFromWindow { void onViewDetachedFromWindow(View v); } @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewAttachedToWindow { void onViewAttachedToWindow(View v); }
하나의 리스너를 변경하면 다른 리스너가 영향을 받을 수 있으므로
둘 중 하나 또는 둘 다에
사용할 수 있습니다 다음에서 requireAll
를 false
로 설정할 수 있습니다.
일부 속성에 바인딩을 할당할 필요가 없음을 지정하는 주석
표현식을 사용해야 합니다.
Kotlin
@BindingAdapter( "android:onViewDetachedFromWindow", "android:onViewAttachedToWindow", requireAll = false ) fun setListener(view: View, detach: OnViewDetachedFromWindow?, attach: OnViewAttachedToWindow?) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { val newListener: View.OnAttachStateChangeListener? newListener = if (detach == null && attach == null) { null } else { object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { attach.onViewAttachedToWindow(v) } override fun onViewDetachedFromWindow(v: View) { detach.onViewDetachedFromWindow(v) } } } val oldListener: View.OnAttachStateChangeListener? = ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener) if (oldListener != null) { view.removeOnAttachStateChangeListener(oldListener) } if (newListener != null) { view.addOnAttachStateChangeListener(newListener) } } }
자바
@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}, requireAll=false) public static void setListener(View view, OnViewDetachedFromWindow detach, OnViewAttachedToWindow attach) { if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) { OnAttachStateChangeListener newListener; if (detach == null && attach == null) { newListener = null; } else { newListener = new OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { if (attach != null) { attach.onViewAttachedToWindow(v); } } @Override public void onViewDetachedFromWindow(View v) { if (detach != null) { detach.onViewDetachedFromWindow(v); } } }; } OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener); if (oldListener != null) { view.removeOnAttachStateChangeListener(oldListener); } if (newListener != null) { view.addOnAttachStateChangeListener(newListener); } } }
위의 예는
View
클래스는
addOnAttachStateChangeListener()
및
removeOnAttachStateChangeListener()
setter 메서드 대신
OnAttachStateChangeListener
.
android.databinding.adapters.ListenerUtil
클래스는 이러한 항목을 추적하는 데 도움이 됩니다.
리스너가 결합 어댑터에서 삭제될 수 있도록 해야 합니다.
객체 변환
자동 객체 변환
결합에서 Object
가 반환되는 경우
라이브러리는
속성 Object
는 선택한 메서드의 매개변수 유형으로 변환됩니다. 이
편리한 동작은
ObservableMap
클래스를 다음 대상에게:
데이터를 저장합니다.
<TextView
android:text='@{userMap["lastName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
표현식의 userMap
객체는 자동으로 값을 반환하며
다음을 수행하는 데 사용된 setText(CharSequence)
메서드에서 찾을 수 있는 매개변수 유형으로 변환
android:text
속성의 값을 설정합니다. 매개변수 유형이
모호하지 않으면 표현식의 반환 유형을 변환합니다.
맞춤 변환
어떤 상황에서는 특정 유형 간에 맞춤 변환이 필요합니다. 대상
예를 들어 뷰의 android:background
속성에는 Drawable
이 필요하지만
지정된 color
값이 정수입니다. 다음 예는
속성: Drawable
을 예상하지만 정수가 대신 제공됩니다.
<View
android:background="@{isError ? @color/red : @color/white}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Drawable
가 예상되고 정수가 반환될 때마다 int
를 변환합니다.
ColorDrawable
로 변경합니다.
변환을 수행하려면
BindingConversion
드림
주석을 추가합니다.
Kotlin
@BindingConversion fun convertColorToDrawable(color: Int) = ColorDrawable(color)
자바
@BindingConversion public static ColorDrawable convertColorToDrawable(int color) { return new ColorDrawable(color); }
그러나 결합 표현식에 지정하는 값 유형은 일관되어야 합니다. 다음과 같이 동일한 표현식에 다른 유형을 사용할 수 없습니다. 예:
// The @drawable and @color represent different value types in the same
// expression, which causes a build error.
<View
android:background="@{isError ? @drawable/error : @color/white}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
추가 리소스
데이터 결합에 관한 자세한 내용은 다음 리소스를 참고하세요.
샘플
Codelab
블로그 게시물
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- 데이터 결합 라이브러리
- 레이아웃 및 바인딩 수식
- 뷰 결합