지난번 안드로이드에서 뷰에 접근하는 방법으로 findViewById, dataBinding을 비교하여 정리를 해봤는데 이번에는 안드로이드에서 대표적으로 뷰에 접근하는 방법인 findViewById,Kotlin Android Extensions,DataBinding,ViewBinding을 비교하고 정리하는 글을 쓰려고 한다.
가장 기본적이고 간단한 방법으로 View의 id값을 기반으로 Activity에서 View에 접근하는 방법이다. DataBinding,ViewBinding에 비해 비교적 간단하지만 타입 안전성 부족,코드의 중복,성능 문제등의 단점이 존재한다.
<?xml version="1.0" encoding="utf-8"?>
<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=".access_view.FindViewByIdActivity"
android:orientation="vertical">
<Button
android:id="@+id/findViewByIdBtn1"
android:text="findViewByIdBtn1"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/findViewByIdBtn2"
android:text="findViewByIdBtn2"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/findViewByIdBtn3"
android:text="findViewByIdBtn3"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
class FindViewByIdActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_find_view_by_id)
findViewById<Button>(R.id.findViewByIdBtn1).text = "abcd"
findViewById<Button>(R.id.findViewByIdBtn2).text = "abcd"
findViewById<Button>(R.id.findViewByIdBtn3).text = "abcd"
}
}
현재는 지원하지 않는 방식으로써 기존에는 findViewById없이 편리하게 뷰에 접근할 수 있도록 해주었지만
id로 구분하지 않기 때문에 다른 xml 파일의 뷰에 접근하게 될 경우 에러가 발생, 성능 저하등 여러가지 문제로 현재는 사용되지 않는다.
findViewById,Kotlin Android Extensions 보다는 사용방법이 조금 복잡하지만 코드의 안전성과 생산성을 높이는 데 큰 도움이 된다. findViewById 방법과는 다르게 타입안전성,null안전성,성능 향상등 여러가지 장점이 있기 때문에 널리 사용되고 있는 방법이다.
View Binding은 Activity,Fragment에 따라서 사용되는 방법 다르기 때문에 각각 정리하도록 하겠다.
우선 View Binding을 사용할수 있도록 gradle에 추가한다.
<?xml version="1.0" encoding="utf-8"?>
<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=".access_view.ViewBindingActivity">
<TextView
android:id="@+id/viewBindingText"
android:text="View Binding"
android:textSize="50sp"
android:textStyle="bold"
android:textColor="@color/black"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
class ViewBindingActivity : AppCompatActivity() {
private lateinit var binding : ActivityViewBindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityViewBindingBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.viewBindingText.text = "Activity : View Binding 성공"
binding.viewBindingText.setOnClickListener{
startActivity(Intent(this,ViewBindingFragmentActivity::class.java))
}
}
}
<androidx.constraintlayout.widget.ConstraintLayout 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=".access_view.ViewBindingFragmentActivity">
<FrameLayout
android:id="@+id/frameArea"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
class ViewBindingFragmentActivity : AppCompatActivity() {
val manager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_binding_fragment)
val transaction = manager.beginTransaction()
val fragment = ViewBindingFragment()
transaction.replace(R.id.frameArea,fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".access_view.ViewBindingFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/fragmentText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="40sp"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
class ViewBindingFragment : Fragment() {
private var _binding : FragmentViewBindingBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentViewBindingBinding.inflate(inflater,container,false)
val view = binding.root
binding.fragmentText.text = "Fragment : View Binding 성공"
return view
}
}
Data Binding 또한 findViewById,Kotlin Android Extensions 보다는 사용방법이 조금 복잡하지만 코드의 안전성과 생산성을 높이는 데 큰 도움이 된다. ViewBindig보다 설정이 다소 불편하며, 성능이 떨어질수 있지만, 양방향 바인딩 지원, MVVM 패턴과 잘 어울리며, 코드와 UI의 명확한 분리를 통해 가독성이 좋다.
Data Binding 또한 Activity,Fragment에 따라서 사용되는 방법 다르기 때문에 각각 정리하도록 하겠다.
우선 Data Binding을 사용할수 있도록 gradle에 추가한다.
<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"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".access_view.DataBindingActivity">
<TextView
android:id="@+id/dataBindingText"
android:text="Data Binding"
android:textSize="50sp"
android:textStyle="bold"
android:textColor="@color/black"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
class DataBindingActivity : AppCompatActivity() {
private lateinit var bindng : ActivityDataBindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindng = DataBindingUtil.setContentView(this,R.layout.activity_data_binding)
bindng.dataBindingText.text = "Activity : Data Binding 성공"
bindng.dataBindingText.setOnClickListener{
startActivity(Intent(this,DataBindingFragmentActivity::class.java))
}
}
}
// viewBinding 과 같은 방식으로 프래그 먼트와 액티비티를 연결시켜준다.
// viewBinding 과 같은 방식으로 프래그 먼트와 액티비티를 연결시켜준다.
<?xml version="1.0" encoding="utf-8"?>
<layout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".access_view.DataBindingFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/fragmentText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="40sp"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
</layout>
class DataBindingFragment : Fragment() {
private lateinit var binding : FragmentDataBindingBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.fragment_data_binding,container,false)
binding.fragmentText.text = "Fragment : Data Binding 성공"
// Inflate the layout for this fragment
return binding.root
}
}
findViewById,Kotlin Android Extensions,View Binding,Data Binding의 장단점과 사용방법에 대해 정리해보았다. 확실히 사용하기 편한것은 많은 단점,리스크가 존재 하는것 같다. 프로젝트의 요구사항,복잡성에따라서 사용하는 것이 좋을것 같고, 특히 데이터와 UI의 상호작용이 많은 경우 mvvm 패턴을 적극 사용할수 있는 데이터 바인딩 방법을 사용하는 것이 좋을것 같다.