[Android/Jetpack]Databinding 사용하기

2023. 2. 24. 09:56Android/Jetpack

728x90
반응형

(1) 기본 세팅

build.gradle (java는 아래 코드만 추가)

android {
...
dataBinding {
        enabled = true
    }
...
}

build.gradle (kotlin의 경우, 아래 코드도 추가)

apply plugin: 'kotlin-kapt'
...
dependencies {
    ...
    // 버전은 본인 gradle 버전으로 작성
    kapt 'com.android.databinding:compiler:3.5.3'
    ...
}

(2) xml 수정

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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>
    ...
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btnSample"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button"
         />

    </LinearLayout>
</layout>
  • 기존 xml 태그 최상위에 이라는 태그로 전체를 감싸줌
  • 태그 안에는 xml에서 사용할 변수들을 태그를 이용해 작성해줌

(3) kotlin 파일 수정

MainActivity.kt

private lateinit var binding: ActivityMainBinding
...

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
         ...

    }
  • 기존에 존재했던 setContentView가 다른 걸로 대체
    • xml의 이름 기준으로 □□□Binding이라는 클래스가 자동으로 만들어짐
  • xml의 변수를 참조하고 싶을 경우에는 'binding.뷰이름'으로 불러옴

(4) 버튼 클릭 이벤트

MainActivity.kt

 fun btnClick(view : View){
        // 이 안에 원하는 실행 메세지 작성
}

activity_main.xml

...
<data>
    <variable
        name="activity"
        type="org.techtown.databinding.MainActivity" />
</data>
...
  • 태그 안에 로 activity라는 이름의 변수를 설정함 (아름은 자유)
  • type은 해당 경로
...
<Button
    android:id="@+id/btnSample"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="button"
    android:onClick="@{activity::btnClick}"/>
...
  • 기존에 존재했던 btnSample이라는 이름의 버튼에 다음과 같이 onClick 속성을 추가
    • @{변수 이름 :: 함수 이름}
      • 함수 이름 같은 경우는 실제 액티비티에 존재하는 함수 이름과 일치해야 하며, 반드시 :: 을 써야함

(5) 액티비티에서 해당 변수(variable)에 값을 넣어줌

MainAcitivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
        binding.activity = this@MainActivity
    }
    ...

2) RecyclerView에서 각각의 아이템을 데이터 바인딩을 이용해 사용

(1) data class 생성 (이름과 나이 저장)

ProfileData.kt

data class ProfileData(
    var name : String,
    var age : Int
)

(2) xml 수정

<?xml version="1.0" encoding="utf-8"?>
<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="activity"
            type="org.techtown.databinding.MainActivity" />

    </data>

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

        <Button
            android:id="@+id/btnSample"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="button"
            android:onClick="@{activity::btnClick}"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/mainRcv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</layout>

(3) RecyclerView Layout 생성

<?xml version="1.0" encoding="utf-8"?>
<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="org.techtown.databinding.ProfileData" />
    </data>

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

        <TextView
            android:id="@+id/item_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:text="Title"
            android:textSize="30sp"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:paddingLeft="10dp"
            android:text="@{user.name}"/>

        <TextView
            android:id="@+id/item_age"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            tools:text="Age"
            android:textSize="20sp"
            android:gravity="center_vertical"
            android:padding="10dp"
            android:text="@{Integer.toString(user.age)}"/>

    </LinearLayout>
</layout>
  • user라는 이름의 변수로 태그 안에 만들어 주고, 값들이 들어갈 텍스트뷰에 맞춰 ProfileData에 존재하는 변수를 넣어줌

(4) ViewHolder 수정

기존 ViewHolder

class BaseVH(view : View) : RecyclerView.ViewHolder(view){
        val name : TextView = view.findViewById(R.id.item_name)
        val age : TextView = view.findViewById(R.id.item_age)

        fun onbind(data : ProfileData){
            name.text = data.name
            age.text = data.age.toString()
        }

}

데이터바인딩 ViewHolder

 class ProfileVH(val binding : RcvListItemBinding) : RecyclerView.ViewHolder(binding.root){
        fun onBind(data : ProfileData){
            binding.user = data
        }
    }

(5) Adapter 수정

기본 Adapter

class BaseAdapter (val context : Context) : RecyclerView.Adapter<BaseAdapter.BaseVH>(){

    var data = listOf<ProfileData>()
    ...
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseAdapter.BaseVH {
        val view  = LayoutInflater.from(context)
            .inflate(R.layout.rcv_list_item, parent, false)
        return BaseVH(view)
    }
    ...
}

데이터바인딩 Adapter

class ProfileAdapter (private val context : Context) : RecyclerView.Adapter<ProfileAdapter.ProfileVH>(){

    var data = listOf<ProfileData>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileVH {
      val binding = RcvListItemBinding.inflate(
          LayoutInflater.from(context), parent, false)

        return ProfileVH(binding)
    }

    ...
}

(6) MainActivity 수정

class MainActivity : AppCompatActivity() {    
   private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        setRcv()
        ...
    }

    ...

    fun setRcv(){
        val profileAdapter = ProfileAdapter(this)
        binding.mainRcv.layoutManager = LinearLayoutManager(this)
        binding.mainRcv.adapter = profileAdapter
        profileAdapter.data = listOf(
            ProfileData(name = "Kang", age = 26),
            ProfileData(name = "Kim", age = 25)
        )
        profileAdapter.notifyDataSetChanged()
    }
}
728x90
반응형