[AAC] Data Binding

dwjeongΒ·2023λ…„ 11μ›” 8일
0

μ•ˆλ“œλ‘œμ΄λ“œ

λͺ©λ‘ 보기
14/28
post-custom-banner

πŸ”Ž 데이터 λ°”μΈλ”©μ΄λž€

ν”„λ‘œκ·Έλž˜λ°μ μœΌλ‘œκ°€ μ•„λ‹Œ 선언적 ν˜•μ‹μ„ μ‚¬μš©ν•˜μ—¬ μ•±μ˜ 데이터 μ†ŒμŠ€μ™€ λ ˆμ΄μ•„μ›ƒ UI μ»΄ν¬λ„ŒνŠΈλ₯Ό 바인딩할 수 μžˆλ„λ‘ ν—ˆμš©ν•˜λŠ” 라이브러리.

λ ˆμ΄μ•„μ›ƒμ€ μ’…μ’… μ•‘ν‹°λΉ„ν‹°μ—μ„œ UI ν”„λ ˆμž„μ›Œν¬ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” μ½”λ“œμ™€ ν•¨κ»˜ μ •μ˜λ¨.

findViewById<TextView>(R.id.sample_text).apply {
    text = viewModel.userName
}

ν•˜μ§€λ§Œ Data Binding 라이브러리λ₯Ό μ‚¬μš©ν•˜μ—¬ λ ˆμ΄μ•„μ›ƒ νŒŒμΌμ—μ„œ μœ„μ ―μ— 직접 ν…μŠ€νŠΈλ₯Ό ν• λ‹Ήν•  수 있음.

<TextView
    android:text="@{viewmodel.userName}" />

πŸ’‘ μž₯점

λ ˆμ΄μ•„μ›ƒ νŒŒμΌμ—μ„œ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ°”μΈλ”©ν•˜λ©΄ μ•‘ν‹°λΉ„ν‹°μ—μ„œ λ§Žμ€ UI ν”„λ ˆμž„μ›Œν¬ ν˜ΈμΆœμ„ μ œκ±°ν•˜μ—¬ μ•‘ν‹°λΉ„ν‹°λ₯Ό 더 κ°„λ‹¨ν•˜κ³  μœ μ§€ κ΄€λ¦¬ν•˜κΈ° μ‰½κ²Œ λ§Œλ“€ 수 있음.

πŸ‘‰ μ•±μ˜ μ„±λŠ₯을 ν–₯μƒμ‹œν‚€κ³  λ©”λͺ¨λ¦¬ λˆ„μˆ˜μ™€ 널 포인터 μ˜ˆμ™Έλ₯Ό 방지.


πŸ“ μ‚¬μš© ν™˜κ²½ μ„€μ •

μ•± λͺ¨λ“ˆμ˜ build.gradle νŒŒμΌμ—μ„œ dataBinding λΉŒλ“œ μ˜΅μ…˜ ν™œμ„±ν™”.

android {
    ...
    buildFeatures {
        dataBinding true
    }
}



πŸ“ λ ˆμ΄μ•„μ›ƒ 및 바인딩 ν‘œν˜„μ‹

ν‘œν˜„μ‹ μ–Έμ–΄λ₯Ό μ‚¬μš©ν•˜λ©΄ λ³€μˆ˜λ₯Ό λ ˆμ΄μ•„μ›ƒμ˜ 뷰에 μ—°κ²°ν•˜λŠ” ν‘œν˜„μ‹μ„ μž‘μ„±ν•  수 있음.
데이터 바인딩 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λ ˆμ΄μ•„μ›ƒ λ·°λ₯Ό 데이터 객체와 μžλ™μœΌλ‘œ μ—°κ²°ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ 클래슀λ₯Ό μžλ™μœΌλ‘œ 생성함. λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λ ˆμ΄μ•„μ›ƒμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” imports, variables 및 includes 같은 κΈ°λŠ₯ 제곡.

<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="viewmodel"
            type="com.myapp.data.ViewModel" />
    </data>
    <ConstraintLayout... /> <!-- UI layout's root element -->
</layout>



데이터 바인딩 λ ˆμ΄μ•„μ›ƒ νŒŒμΌμ€ layout 루트 νƒœκ·Έλ‘œ μ‹œμž‘ν•˜λ©°, data element와 view root elementκ°€ μ΄μ–΄μ„œ μž‘μ„±λ¨. view elementλŠ” 일반 λ ˆμ΄μ•„μ›ƒ 파일과 λ™μΌν•˜κ²Œ μž‘μ„±.

μ˜ˆμ‹œ μ½”λ“œ)

<?xml version="1.0" encoding="utf-8"?>
<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}"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"/>
   </LinearLayout>
</layout>



λ ˆμ΄μ•„μ›ƒ λ‚΄μ—μ„œμ˜ ν‘œν˜„μ‹μ€ @{} ꡬ문을 μ‚¬μš©ν•˜μ—¬ 속성 ν”„λ‘œνΌν‹°μ— μž‘μ„±λ¨.

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="@{user.firstName}" />




πŸ“š 데이터 바인딩

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

    val binding: ActivityMainBinding = DataBindingUtil.setContentView(
            this, R.layout.activity_main)

    binding.user = User("Test", "User") //λŸ°νƒ€μž„ μ‹œ UI에 Test userλ₯Ό ν‘œμ‹œ
}

각 λ ˆμ΄μ•„μ›ƒ νŒŒμΌμ— λŒ€ν•΄ 바인딩 ν΄λž˜μŠ€κ°€ 생성됨. 기본적으둜 클래슀 이름은 λ ˆμ΄μ•„μ›ƒ 파일의 이름을 파슀칼 ν‘œκΈ°λ²•μœΌλ‘œ λ³€ν™˜ν•œ 것이며 여기에 Binding 접미사가 좔가됨.(λ·° 바인딩과 동일)



LayoutInflaterλ₯Ό μ‚¬μš©ν•˜μ—¬ λ·°λ₯Ό κ°€μ Έμ˜¬ μˆ˜λ„ 있음.

val binding: ActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater())

Fragment, ListView λ˜λŠ” RecyclerView μ–΄λŒ‘ν„° λ‚΄μ—μ„œ 데이터 바인딩 ν•­λͺ©μ„ μ‚¬μš©ν•˜λŠ” 경우, 바인딩 클래슀 λ˜λŠ” DataBindingUtil 클래슀의 inflate() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  수 있음.

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




πŸ“š ν‘œν˜„μ‹ μ–Έμ–΄

λ‹€μŒ μ—°μ‚°μžλ₯Ό ν‘œν˜„μ‹ μ–Έμ–΄μ—μ„œ μ‚¬μš©ν•  수 있음.

  • Mathematical: + - / * %
  • String concatenation: +
  • Logical: && ||
  • Binary: & | ^
  • Unary: + - ! ~
  • Shift: >> >>> <<
  • Comparison: == > < >= <= (the < needs to be escaped as <)
  • instanceof
  • Grouping: ()
  • Literals, such as character, String, numeric, null
  • Cast
  • Method calls
  • Field access
  • Array access: []
  • Ternary operator: ?:
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'

πŸ“š 널 병합 μ—°μ‚°μž

널 병합 μ—°μ‚°μž (??)λŠ” μ™Όμͺ½ ν”Όμ—°μ‚°μžκ°€ null이 μ•„λ‹Œ 경우 μ™Όμͺ½μ„ μ„ νƒν•˜κ³ , μ™Όμͺ½μ΄ null인 경우 였λ₯Έμͺ½μ„ 선택함.

android:text="@{user.displayName ?? user.lastName}"

<!--μ•„λž˜ μ½”λ“œμ™€ λ™μΌν•œ μ½”λ“œμž„-->
android:text="@{user.displayName != null ? user.displayName : user.lastName}"

πŸ“š ν”„λ‘œνΌν‹° μ°Έμ‘°, λ·° μ°Έμ‘°

ν‘œν˜„μ‹μ€ ν•„λ“œ, κ²Œν„°, ObservableField 객체에 λŒ€ν•΄ λ™μΌν•œ ν˜•μ‹μ„ μ‚¬μš©ν•˜μ—¬ 클래슀 λ‚΄ 속성을 μ°Έμ‘°ν•  수 있음.

android:text="@{user.lastName}"

λ‹€μŒ ꡬ문을 μ‚¬μš©ν•˜μ—¬ λ ˆμ΄μ•„μ›ƒ λ‚΄μ˜ λ‹€λ₯Έ λ·°λ₯Ό ID둜 μ°Έμ‘°ν•  수 있음.
⭐ 바인딩 ν΄λž˜μŠ€λŠ” IDλ₯Ό 카멜 μΌ€μ΄μŠ€λ‘œ λ³€ν™˜.

android:text="@{exampleText.text}"
<EditText
    android:id="@+id/example_text"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"/>
<TextView
    android:id="@+id/example_output"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{exampleText.text}"/>

πŸ“š μ»¬λ ‰μ…˜

λ°°μ—΄, 리슀트, ν¬μ†Œ 리슀트 및 맡과 같은 일반 μ»¬λ ‰μ…˜μ— [] μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ νŽΈν•˜κ²Œ μ ‘κ·Ό κ°€λŠ₯.

<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.Map"/>
    <import type="java.util.List"/>
    <variable name="list" type="List&lt;String>"/>
    <variable name="sparse" type="SparseArray&lt;String>"/>
    <variable name="map" type="Map&lt;String, String>"/>
    <variable name="index" type="int"/>
    <variable name="key" type="String"/>
</data>
...
android:text="@{list[index]}"
...
android:text="@{sparse[index]}"
...
android:text="@{map[key]}"

⭐ xml 문법을 μ˜¬λ°”λ₯΄κ²Œ μž‘μ„±ν•˜κΈ° μœ„ν•΄ < 문자λ₯Ό μ΄μŠ€μΌ€μ΄ν”„ν•΄μ•Ό 함. List<String> λŒ€μ‹  List&lt;String> 와 같이 μž‘μ„±. λ§΅μ—μ„œ 값을 μ°Έμ‘°ν•  λ•Œ object.key ν‘œκΈ°λ²• μ‚¬μš© κ°€λŠ₯.
예λ₯Ό λ“€μ–΄ @{map[key]}λ₯Ό @{map.key}둜 λŒ€μ²΄


πŸ“š 이벀트 처리

데이터 바인딩을 μ‚¬μš©ν•˜λ©΄ λ·°μ—μ„œ μ „λ‹¬λ˜λŠ” 이벀트λ₯Ό μ²˜λ¦¬ν•˜λŠ” ν‘œν˜„μ‹μœΌλ‘œ μž‘μ„±ν•  수 있음.

πŸ’‘ 이벀트 처리λ₯Ό μœ„ν•œ 두 가지 λ©”μ»€λ‹ˆμ¦˜

  1. Method references
    ν‘œν˜„μ‹μ΄ λ©”μ„œλ“œ 참쑰둜 μ‹€ν–‰λ˜λ©΄ 데이터 바인딩은 λ©”μ„œλ“œ 참쑰와 μ†Œμœ μž 객체λ₯Ό λ¦¬μŠ€λ„ˆμ— λž˜ν•‘ν•˜κ³  ν•΄λ‹Ή λ¦¬μŠ€λ„ˆλ₯Ό λŒ€μƒ 뷰에 섀정함.
    ν‘œν˜„μ‹μ΄ null둜 ν‰κ°€λ˜λ©΄ 데이터 바인딩은 λ¦¬μŠ€λ„ˆλ₯Ό μƒμ„±ν•˜μ§€ μ•Šκ³  null λ¦¬μŠ€λ„ˆλ₯Ό 섀정함.

  2. Listener bindings
    이벀트 λ°œμƒ μ‹œμ— μ‹€ν–‰λ˜λŠ” λžŒλ‹€ ν‘œν˜„μ‹. 데이터 바인딩은 항상 λ¦¬μŠ€λ„ˆλ₯Ό μƒμ„±ν•˜κ³  ν•΄λ‹Ή λ¦¬μŠ€λ„ˆλ₯Ό 뷰에 섀정함. μ΄λ²€νŠΈκ°€ λ°œμƒν•˜λ©΄ λ¦¬μŠ€λ„ˆκ°€ λžŒλ‹€ ν‘œν˜„μ‹μ„ 싀행함.


Method references

이벀트λ₯Ό ν•Έλ“€λŸ¬ λ©”μ„œλ“œμ— 직접 바인딩할 수 있으며 μ΄λŠ” μ•‘ν‹°λΉ„ν‹°μ—μ„œ android.onClick λ©”μ„œλ“œμ— ν• λ‹Ήν•˜λŠ” 방식과 μœ μ‚¬.

View의 onClick 속성과 λΉ„κ΅ν–ˆμ„ λ•Œμ˜ μž₯점은 ν‘œν˜„μ‹μ΄ 컴파일 μ‹œκ°„μ— μ²˜λ¦¬λœλ‹€λŠ” 것.
λ©”μ„œλ“œκ°€ μ‘΄μž¬ν•˜μ§€ μ•Šκ±°λ‚˜ μ‹œκ·Έλ‹ˆμ²˜κ°€ 잘λͺ»λœ 경우 컴파일 νƒ€μž„ 였λ₯˜κ°€ λ°œμƒν•¨.

  • Method references와 Listener bindings의 차이점
    μ‹€μ œ λ¦¬μŠ€λ„ˆ κ΅¬ν˜„μ΄ μ΄λ²€νŠΈκ°€ 트리거될 λ•Œκ°€ μ•„λ‹Œ 데이터 바인딩될 λ•Œ μƒμ„±λœλ‹€λŠ” 것.
    λ¦¬μŠ€λ„ˆ 바인딩은 μ΄λ²€νŠΈκ°€ λ°œμƒν•  λ•Œ ν‘œν˜„μ‹μ΄ 싀행됨.
class MyHandlers {
    fun onClickFriend(view: View) { ... }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="handlers" type="com.example.MyHandlers"/>
       <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:onClick="@{handlers::onClickFriend}"/> <!--λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜μ™€ μ •ν™•νžˆ μΌμΉ˜ν•΄μ•Ό 함-->
   </LinearLayout>
</layout>

Listener bindings

μ΄λ²€νŠΈκ°€ λ°œμƒν•  λ•Œ μ‹€ν–‰λ˜λŠ” 바인딩 ν‘œν˜„μ‹. λ©”μ„œλ“œ 참쑰와 μœ μ‚¬ν•˜μ§€λ§Œ μž„μ˜μ˜ 데이터 바인딩 ν‘œν˜„μ‹ μ‹€ν–‰ κ°€λŠ₯. (Android Gradle ν”ŒλŸ¬κ·ΈμΈ 버전 2.0 μ΄μƒμ—μ„œ μ‚¬μš© κ°€λŠ₯.)

Method referenceμ—μ„œλŠ” λ©”μ„œλ“œμ˜ λ§€κ°œλ³€μˆ˜κ°€ 이벀트 λ¦¬μŠ€λ„ˆμ˜ 맀개 λ³€μˆ˜μ™€ μΌμΉ˜ν•΄μ•Ό 함. (λ©”μ„œλ“œ μ‹œκ·Έλ‹ˆμ²˜κ°€ μ •ν™•νžˆ μΌμΉ˜ν•΄μ•Ό 함)
λ¦¬μŠ€λ„ˆ λ°”μΈλ”©μ—μ„œλŠ” voidλ₯Ό κΈ°λŒ€ν•˜λŠ” 경우λ₯Ό μ œμ™Έν•˜κ³ λŠ” λ°˜ν™˜ κ°’λ§Œ λ¦¬μŠ€λ„ˆμ˜ κΈ°λŒ€ λ°˜ν™˜ κ°’κ³Ό μΌμΉ˜ν•˜λ©΄ 됨.

class Presenter {
    fun onSaveClick(task: Task){}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="task" type="com.android.example.Task" />
        <variable name="presenter" type="com.android.example.Presenter" />
    </data>
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
        <Button android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:onClick="@{() -> presenter.onSaveClick(task)}" />
    </LinearLayout>
</layout>

콜백이 ν‘œν˜„μ‹μ—μ„œ μ‚¬μš©λ  λ•Œ 데이터 바인딩은 ν•„μš”ν•œ λ¦¬μŠ€λ„ˆλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜κ³  ν•΄λ‹Ή μ΄λ²€νŠΈμ— 등둝함.

λ·°κ°€ 이벀트λ₯Ό λ°œμƒμ‹œν‚€λ©΄ 데이터 바인딩은 주어진 ν‘œν˜„μ‹μ„ 싀행함. 이 λ•Œ λ¦¬μŠ€λ„ˆ ν‘œν˜„μ‹μ΄ μ‹€ν–‰λ˜λŠ” λ™μ•ˆ 데이터 λ°”μΈλ”©μ˜ null 및 μŠ€λ ˆλ“œ μ•ˆμ „μ„±μ„ μ œκ³΅λ°›μŒ.

μœ„μ˜ μ½”λ“œλ₯Ό μ•„λž˜μ™€ 같이 μž‘μ„± κ°€λŠ₯.

android:onClick="@{(view) -> presenter.onSaveClick(task)}" <!--onClick(View)에 μ „λ‹¬λ˜λŠ” λ§€κ°œλ³€μˆ˜λ₯Ό λͺ…λͺ…ν•œ 것. λ¬΄μ‹œν•˜κ±°λ‚˜ λͺ¨λ‘ λͺ…λͺ…ν•  수 있음.-->

μ•„λž˜μ™€ 같이 μ‚¬μš© κ°€λŠ₯.

class Presenter {
    fun onSaveClick(view: View, task: Task){}
}
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"

ν•˜λ‚˜λ³΄λ‹€ λ§Žμ€ λ§€κ°œλ³€μˆ˜λ₯Ό 가진 λžŒλ‹€μ‹ μ‚¬μš© κ°€λŠ₯.

class Presenter {
    fun onCompletedChanged(task: Task, completed: Boolean){}
}
<CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content"
      android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />

μ΄λ²€νŠΈκ°€ voidκ°€ μ•„λ‹Œ λ°˜ν™˜κ°’μ„ κ°€μ§ˆ 경우 ν‘œν˜„μ‹μ€ λ™μΌν•œ μœ ν˜•μ˜ λ°˜ν™˜ 값을 λ°˜ν™˜ν•΄μ•Ό 함.

class Presenter {
    fun onLongClick(view: View, task: Task): Boolean { }
}
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"

ν‘œν˜„μ‹μ΄ null 객체둜 인해 μ‹€ν–‰ν•  수 μ—†λŠ” 경우 기본값을 λ°˜ν™˜ν•  수 있음.
삼항식을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 경우 voidλ₯Ό 기호둜 μ‚¬μš©ν•  수 있음.

android:onClick="@{(v) -> v.isVisible() ? doSomething() : void}"



πŸ“š λ³΅μž‘ν•œ λ¦¬μŠ€λ„ˆλŠ” ν”Όν•  것

λ¦¬μŠ€λ„ˆ ν‘œν˜„μ‹μ€ μ½”λ“œλ₯Ό 읽기 μ‰½κ²Œ λ§Œλ“€ 수 있음. κ·ΈλŸ¬λ‚˜ λ³΅μž‘ν•œ ν‘œν˜„μ‹μ„ ν¬ν•¨ν•˜λŠ” λ¦¬μŠ€λ„ˆλŠ” λ ˆμ΄μ•„μ›ƒμ„ 읽고 μœ μ§€ν•˜κΈ° νž˜λ“€κ²Œ λ§Œλ“¦. ν‘œν˜„μ‹μ€ κ°€λŠ₯ν•œ ν•œ κ°„λ‹¨ν•˜κ²Œ μœ μ§€ν•˜κ³  UIμ—μ„œ μ‚¬μš© κ°€λŠ₯ν•œ 데이터λ₯Ό 콜백 λ©”μ„œλ“œλ‘œ 전달. λ¦¬μŠ€λ„ˆ ν‘œν˜„μ‹μ—μ„œ ν˜ΈμΆœν•˜λŠ” 콜백 λ©”μ„œλ“œ λ‚΄μ—μ„œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 κ΅¬ν˜„.




πŸ“ Imports, variables, includes

πŸ“• Imports

Importsλ₯Ό μ‚¬μš©ν•˜λ©΄ λ ˆμ΄μ•„μ›ƒ 파일 λ‚΄μ—μ„œ 클래슀λ₯Ό μ°Έμ‘°ν•  수 있음.
data μš”μ†Œ λ‚΄μ—μ„œ import μš”μ†Œλ₯Ό 0개 이상 μ‚¬μš©ν•  수 있음.

<data>
    <import type="android.view.View"/>
</data>

View 클래슀λ₯Ό κ°€μ Έμ˜€λ©΄ 바인딩 ν‘œν˜„μ‹μ—μ„œ ν•΄λ‹Ή 클래슀λ₯Ό μ°Έμ‘° ν•  수 있음.

<TextView
   android:text="@{user.lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>
  • Type aliases
    클래슀 이름이 μΆ©λŒν•˜λŠ” 경우 ν•˜λ‚˜λ₯Ό λ³„μΉ­μœΌλ‘œ λ°”κΏ€ 수 있음.
<import type="android.view.View"/>
<import type="com.example.real.estate.View"
        alias="Vista"/> <!-- λ³„μΉ­μœΌλ‘œ λ°”κΏˆ -->
  • λ‹€λ₯Έ 클래슀 import
    Import된 νƒ€μž…μ„ λ³€μˆ˜μ™€ ν‘œν˜„μ‹μ—μ„œ type 참쑰둜 μ‚¬μš©ν•  수 있음.
<data>
    <import type="com.example.User"/>
    <import type="java.util.List"/>
    <variable name="user" type="User"/>
    <variable name="userList" type="List&lt;User>"/>
</data>

μΊμŠ€νŒ…μ—λ„ μ‚¬μš© κ°€λŠ₯.

<TextView
   android:text="@{((User)(user.connection)).lastName}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

정적 ν•„λ“œμ™€ λ©”μ„œλ“œλ₯Ό μ°Έμ‘°ν•  λ•Œλ„ import된 μœ ν˜• μ‚¬μš© κ°€λŠ₯.

<data>
    <import type="com.example.MyStringUtils"/>
    <variable name="user" type="com.example.User"/>
</data>
…
<TextView
   android:text="@{MyStringUtils.capitalize(user.lastName)}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>



πŸ“• Variables

data element λ‚΄μ—μ„œ μ—¬λŸ¬ variable element μ‚¬μš© κ°€λŠ₯.
각 variable μš”μ†ŒλŠ” λ ˆμ΄μ•„μ›ƒμ— μ„€μ •ν•  수 μžˆλŠ” 속성을 μ„€λͺ…ν•˜λ©°, λ ˆμ΄μ•„μ›ƒ 파일 λ‚΄μ˜ 바인딩 ν‘œν˜„μ‹μ—μ„œ μ‚¬μš©λ¨.

<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>

variable μœ ν˜•μ€ 컴파일 νƒ€μž„μ— 검사됨. λ³€μˆ˜κ°€ Observable을 κ΅¬ν˜„ν•˜κ±°λ‚˜ Observable μ»¬λ ‰μ…˜μΈ 경우 κ·Έ 사항이 type에 λ°˜μ˜λ˜μ–΄μ•Ό 함.

λ‹€μ–‘ν•œ ꡬ성(κ°€λ‘œλͺ¨λ“œ ν˜Ήμ€ μ„Έλ‘œλͺ¨λ“œ)의 λ ˆμ΄μ•„μ›ƒ 파일이 μ„œλ‘œ λ‹€λ₯Ό λ•Œ λ³€μˆ˜κ°€ 결합됨. μ΄λŸ¬ν•œ λ ˆμ΄μ•„μ›ƒ 파일 κ°„ μΆ©λŒν•˜λŠ” λ³€μˆ˜ μ •μ˜κ°€ μžˆμ–΄μ„œλŠ” μ•ˆλ¨.

μƒμ„±λœ 바인딩 ν΄λž˜μŠ€μ—λŠ” 각 λ³€μˆ˜μ— λŒ€ν•΄ getter와 setterκ°€ 있음. setterκ°€ 호좜될 λ•ŒκΉŒμ§€ λ³€μˆ˜λŠ” 기본값을 μ‚¬μš©.(μ°Έμ‘° μœ ν˜•μ€ null, intλŠ” 0, boolean은 false)



πŸ“• includes

app λ„€μž„ μŠ€νŽ˜μ΄μŠ€μ™€ μ†μ„±μ—μ„œ λ³€μˆ˜ 이름을 μ‚¬μš©ν•˜μ—¬ ν¬ν•¨λœ λ ˆμ΄μ•„μ›ƒμ˜ 바인딩에 λ³€μˆ˜λ₯Ό 전달할 수 있음.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </LinearLayout>
</layout>

μ˜ˆμ‹œ μ½”λ“œ2)

<!--layout_name.xml-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="user"
            type="com.example.User" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Other views and UI elements specific to layout_name.xml -->

        <!-- Include the contact_info.xml layout -->
        <include
            layout="@layout/contact_info"
            bind:user="@{user}" />
    </RelativeLayout>
</layout>
<!-- contact_info.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="user"
            type="com.example.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <!-- Include user-specific data from the variable -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.email}" />
    </LinearLayout>
</layout>

데이터 바인딩은 includeλ₯Ό 직접 μžμ‹μœΌλ‘œ μ‚¬μš©ν•˜λŠ” merge μš”μ†Œλ₯Ό μ§€μ›ν•˜μ§€ μ•ŠμŒ.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <merge><!-- Doesn't work -->
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </merge>
</layout>
post-custom-banner

0개의 λŒ“κΈ€