class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btn1 : Button = findViewById(R.id.btn1)
val btn2 : Button = findViewById(R.id.btn2)
val btn3 : Button = findViewById(R.id.btn3)
btn1.text = "abcd"
btn2.text = "abcd"
btn3.text = "abcd"
secondBtn.text = "sadfasdfasdf"
// 아래 코드는 정의되지 않은 secondBtn이라는 버튼에 접근하려고 하므로 오류가 발생합니다.
// secondBtn.text = "sadfasdfasdf"
}
이와 같이 'findViewById'를 사용하여 뷰에 접근할 수 있습니다. 하지만 이 방법은 실행 시 모든 뷰 계층을 순회하여 해당 ID를 가진 뷰를 찾기 때문에 복잡한 뷰 계층 구조에서는 시간이 오래 걸릴 수 있습니다. 또한 다른 레이아웃 파일에서 같은 ID를 사용하는 경우, 의도하지 않은 뷰에 접근할 위험도 있습니다. 이런 이유로 현재는 'findViewById' 대신 View Binding이나 Data Binding과 같은 방법을 사용하는 것을 권장하고 있습니다.
ViewBinding을 사용하려면 먼저 앱 레벨의 build.gradle에서 아래와 같이 선언합니다.
buildFeatures{
viewBinding = true
}
그런 다음, 아래와 같이 MainActivity에서 사용할 수 있습니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.testText.text= "이거는 변경된 텍스트"
binding.testText.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
}
RecyclerView의 Adapter에서는 아래와 같이 사용합니다.
class CustomViewAdapter(private val dataSet : ArrayList<String>) : RecyclerView.Adapter<CustomViewAdapter.ViewHolder>(){
class ViewHolder(binding : TextRowItemBinding) : RecyclerView.ViewHolder(binding.root) {
val myText : TextView = binding.myText
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = TextRowItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.myText.text= dataSet[position]
}
override fun getItemCount(): Int {
return dataSet.size
}
}
ViewBinding의 장점은 뷰의 직접적인 참조를 제공하므로 null체크가 필요 없고, 각각의 XML 파일에 대한 바인딩 클래스가 생성되므로 클래스 변환 오류를 방지할 수 있습니다. 또한 성능도 뷰 계층을 순회하지 않으므로 findViewById보다 효율적이며, 가독성도 좋습니다.
DataBinding을 사용하려면 먼저 앱 레벨의 build.gradle에서 아래와 같이 선언합니다.
buildFeatures{
dataBinding = true
}
그런 다음, 아래와 같이 MainActivity에서 사용할 수 있습니다.
// DataBinding
// ViewBinding 이랑 뭐가 다른가?
// 이름처럼 데이터를 연결해주는 역할을 할 수 있습니다. (데이터와 같이 결합해서 사용할 수 있음)
// DataBinding + LiveData
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.dataBindingEx.text= "바뀐 텍스트"
binding.dataBindingEx.setOnClickListener{
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
}
데이터 바인딩을 사용하려면 레이아웃 XML 파일에 layout 태그를 사용하여 루트 뷰를 감싸야 합니다.
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="com.bokchi.jetpack_ex.Person" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:textSize="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.age > 30 ? `나이 많음` : `나이 적음`}"
/>
<Button
android:text="btn"
android:onClick="myClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
RecyclerView의 Adapter에서는 아래와 같이 사용합니다.
class CustomDataAdapter(private val dataSet : ArrayList<String>) : RecyclerView.Adapter<CustomDataAdapter.ViewHolder>(){
class ViewHolder(binding : TextRowItemBinding) : RecyclerView.ViewHolder(binding.root) {
val myText : TextView = binding.myText
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// val view = TextRowItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
val view = DataBindingUtil.inflate<TextRowItemBinding>(LayoutInflater.from(parent.context), R.layout.text_row_item, parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.myText.text= dataSet[position]
}
override fun getItemCount(): Int {
return dataSet.size
}
}
DataBinding을 사용하면 UI와 데이터를 쉽게 연결할 수 있습니다. 뷰 바인딩과는 달리 레이아웃 파일 내에서 바로 데이터를 사용할 수도 있습니다.
Person이라는 데이터 클래스를 만들고, 이를 UI와 연결하여 사용하면
data class Person (
val name : String,
val age : Int
)
<?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="com.bokchi.jetpack_ex.Person" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:id="@+id/test"
android:textSize="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}"
/>
<TextView
android:textSize="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Integer.toString(user.age)}"
/>
<TextView
android:textSize="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.age > 30 ? `나이 많음` : `나이 적음`}"
/>
<Button
android:text="btn"
android:onClick="myClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
이렇게 사용하면 UI와 데이터를 연결하여 사용할 수 있습니다.