[Android/Kotlin] 데이터 바인딩(DataBinding)
[모든 포스팅은 개인적 공부를 위해 작성된 글입니다]
<데이터 바인딩(DataBinding)>
- Android JetPack 라이브러리 중 하나
- xml에 데이터 연결하는 작업
- findViewById() 사용하지 않아도 됨
- 자동으로 xml에서 만든 View들을 만들어 줌
- MVVM 패턴, LiveData와 함께 사용(필수인 것은x)
- Observable 사용해 실시간으로 데이터 변경 가능
- RecyclerView 내부 아이템을 set하지 않아도 xml에서 자동으로 처리
- 간결한 코드 작성 가능
<데이터 바인딩으로 버튼에 클릭 리스너 적용하기>
- gradle app 수준
apply plugin: 'kotlin-kapt'
android {
dataBinding{
enabled = true
}
}
dependencies {
kapt 'com.android.databinding:compiler:3.1.4'//맨 마지막 숫자 == gradle 버전
}
*Java의 경우 dataBinding{enabled=true}만 해주면 됨*
- 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"
tools:context=".DataBinding_Activity">
<data>
<variable
name="activity"
type="org.j_______jy.techtown.DataBinding_Activity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="버튼"
android:onClick="@{activity::buttonClick}"/>
</LinearLayout>
</layout>
- <layout> 태그를 최상위에 붙여줌
- 최상위 태그를 layout으로 바꾸고 layout_width, layout_height를 지워주지 않은 바람에 오류가 발생했다.. 나 같은 실수를 하지 않게 조심하자ㅜㅜ
- <data> 태그 내부
- name은 변수 이름을 의미하고 type은 해당 클래스의 경로 의미
- 처음에 name을 databinding_activity로 했더니 오류 남(_을 쓰면 안되는건지 내가 놓치고 있는 무언가가 있는 것인지 의문..)
- DataBinding_Activity.kt 파일
class DataBinding_Activity : AppCompatActivity() {
private lateinit var binding: ActivityDataBindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_data_binding)
binding.activity = this@DataBinding_Activity
}
fun buttonClick(view: View){
Log.d("click","클릭")
}
}
- ActivityDataBindingBinding : xml 파일명인 activity_data_binding.xml이 파스칼 표기법으로 바뀐 것
- setContentView 부분을 위와 같이 변경
- 기존의 버튼에 직접 리스너 달아주었던 것과 달리 클릭 시 호출 할 함수(buttonClick)만 선언
- 반드시 click 함수의 파라미터로 View를 전달해줘야 함
- 프로젝트 새로 생성했다가 binding.activity = this를 깜빡해 한참 헤맸다.. 다음에는 이런 실수 하지 않게 조심하자..(정말 바보 같은 행동이었다...........)
- Fragment에서 사용하는 경우
lateinit var binding: FragmentLoginBinding
- onCreateView 내부
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)
binding.loginFragment = this@LoginFragment
return binding.root
<RecyclerView에서 데이터 바인딩 사용하기>
- xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="recyclerview"
type="org.j_______jy.domain.item.ToDo" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/title_textView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="9"
android:text="@{recyclerview.title}"/>
<Button
android:id="@+id/delete_button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
</layout>
- Adapter 클래스
package org.j_______jy.todo_is.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.j_______jy.domain.item.ToDo
import org.j_______jy.todo_is.databinding.ActivityMainBinding
import org.j_______jy.todo_is.databinding.TodoRecyclerviewBinding
class ToDo_RecyclerView_Adapter(private val context: Context): RecyclerView.Adapter<ToDo_RecyclerView_Adapter.ViewHolder>() {
var data = listOf<ToDo>()
class ViewHolder(val binding: TodoRecyclerviewBinding): RecyclerView.ViewHolder(binding.root){
fun onBind(data: ToDo){
binding.recyclerview = data
binding.titleTextView.setOnClickListener {
}//타이틀 클릭
binding.deleteButton.setOnClickListener {
}//삭제 클릭
}//onBind
}//ViewHolder
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = TodoRecyclerviewBinding.inflate(LayoutInflater.from(context), parent, false)
return ViewHolder(binding)
}//onCreateViewHolder
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.onBind(data[position])
}//onBindViewHolder
override fun getItemCount(): Int {
return data.size
}//getItemCount
}
- MainActivity
binding.recyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
adapter = ToDo_RecyclerView_Adapter(this@MainActivity)
binding.recyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
binding.recyclerView.adapter = adapter
viewModel.get_ToDo()
val recyclerView_data = Observer<List<ToDo>> {
adapter.data = it
adapter.notifyDataSetChanged()
}
viewModel.todo_data.observe(this@MainActivity, recyclerView_data)