findViewById는 뷰의 ID를 기반으로 XML 레이아웃 파일에 정의된 뷰 요소를 찾아 반환하는 메서드로 일반적으로 액티비티(Activity)나 프래그먼트(Fragment)에서 XML 레이아웃 파일의 뷰요소에 접근하는 방법이다.
하지만 findViewById 메소드를 통해 뷰 객체를 하나씩 가져오게 되면서 성능상으로 좋지 않아 보통 DataBinding이나 ViewBinding을 사용한다고 한다.
이런식으로 .xml 파일에 접근하려는 요소에 id값을 지정한다.
<TextView
android:id="@+id/textView"
android:textSize="30sp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="findViewById Test Text"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="findViewById Test Btn1"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:layout_editor_absoluteX="20dp" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="findViewById Test Btn2"
app:layout_constraintTop_toBottomOf="@+id/button1" />
MainActivity에서는 findViewById()를 통해 id값으로 해당 요소를 참조한다.
class MainActivity : AppCompatActivity() {
private val TAG = MainActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val text : TextView = findViewById(R.id.textView)
val button1 : Button = findViewById(R.id.button1)
val button2 : Button = findViewById(R.id.button2)
text.setOnClickListener{
Log.d(TAG,text.text.toString())
}
button1.setOnClickListener{
Log.d(TAG,button1.text.toString())
}
button2.setOnClickListener{
Log.d(TAG,button1.text.toString())
}
}
}
정상 작동하는지 확인을 위해 setOnClickListener를 이용해 클릭을 감지하고, 클릭이 되면 해당요소의 text를 Log로 찍어보았다.
findViewById를 사용하면 XML 레이아웃 파일에서 정의된 각 뷰를 코드에서 참조하기 위해 일일이 메서드를 호출해야 하기 때문에 많은 뷰를 다루는 경우 코드가 복잡하고 길어질 수 있다. 그리고 findViewById는 뷰를 찾기 위해 트리 구조를 순회합니다. 따라서 복잡한 레이아웃에서 많은 뷰를 반복적으로 찾을 경우 성능이 저하된다.
안드로이드 DataBinding 라이브러리는 UI 요소를 XML 레이아웃과 애플리케이션의 데이터 소스 간에 바인딩(binding)하는 기능을 제공하는 도구로써, 이를 통해 XML 레이아웃 파일 내에서 직접 데이터 소스와 UI 요소를 연결할 수 있어 코드의 간결함과 유지보수성을 높이는 데 도움이 된다.
<layout>
<LinearLayout 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"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FindViewByIdTestActivity"
android:orientation="vertical"
>
<TextView
android:id="@+id/FBVText"
android:textSize="30sp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="findViewById Test Text" />
<Button
android:id="@+id/FBVBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="findViewById Test Btn"
tools:layout_editor_absoluteX="20dp" />
<TextView
android:layout_marginTop="100dp"
android:id="@+id/DBText"
android:textSize="30sp"
android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="dataBinding Test Text" />
<Button
android:id="@+id/DBBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="dataBinding Test Btn"
tools:layout_editor_absoluteX="20dp" />
</LinearLayout>
</layout>
class FindViewByIdTestActivity : AppCompatActivity() {
private val TAG = FindViewByIdTestActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_find_view_by_id_test)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val binding: ActivityFindViewByIdTestBinding = DataBindingUtil.setContentView(this, R.layout.activity_find_view_by_id_test)
// findByView
val FBVText : TextView = findViewById(R.id.FBVText)
val FBVBtn : Button = findViewById(R.id.FBVBtn)
FBVText.setOnClickListener{
Log.d(TAG,FBVText.text.toString())
}
FBVBtn.setOnClickListener{
Log.d(TAG,FBVBtn.text.toString())
}
// dataBinding
val DBText : TextView = binding.DBText
val DBBtn : Button = binding.DBBtn
DBText.setOnClickListener{
Log.d(TAG,DBText.text.toString())
}
DBBtn.setOnClickListener{
Log.d(TAG,DBBtn.text.toString())
}
}
}
dataBindg을 사용하게 되면 초기설정이 다소 복잡할수는 있지만, 코드의 간결함, 타입 안전성, 자동화된 UI 업데이트, MVVM 패턴 지원 등 많은 장점을 제공한다.
findViewById,dataBinding 방식 모두 정상 작동한다.
findViewById는 간단한 뷰 참조에는 여전히 유용할 수 있지만 성능, 코드의 간결성 측면에서 단점이 있습니다. 이러한 문제를 해결하기 위에서 정리한 Data Binding과 추가로 View Binding같은 대안들을 사용할수 있고 , 특히 대규모 애플리케이션에서 더 나은 유지보수성과 성능을 제공한다.