findViewById... findViewById... find..View...by...... 😵💫😵💫
findViewById에 지치셨나요??
🧐 언제까지 ViewId를 찾아다니실 건가요?
이제는 findViewById 없이 View Id 값을 바로 호출 할 수 있습니다.
DataBinding와 함께라면요!
DataBinding 활용하기(1)
✔️ Data Binding이란?
✔️ Data Binding 세팅
✔️ Binding 활용
✔️ @Binding Adapter 사용법
✔️ @Binding Adapter 매개변수 여러개 사용하기
DataBinding 활용하기(2)
✔️ Recyclervie에서 Data Binding 사용
✔️ BR
✔️ Data Binding 단점
📝 Data Binding이란?
Android JetPack 라이브러리 기능 중 하나로
xml의 데이터를 바인딩하여 불필요한 코드를 줄이는 방법입니다.
MVVM패턴을 구현할 때 LiveData와 같이 자주 사용됩니다.
" UI 요소와 데이터를 복잡한 로직으로 연결하지 않고
선언적인 방식으로 결합 가능하게 도와주는 도구 "
(이렇게 글로 나열될 정의만 보면 이해하기 쉽지 않죠! 저도 그렇습니다!)
그렇다면 예제 소스를 통해 알아보시죠! 💁♂️💁♂️
🛠 Data Binding 세팅
Data Binding을 사용하기 위해서는 몇 가지 세팅이 필요합니다.
우선 build.gradle 파일에 dataBinding 속성을 추가합니다.
build.gradle(Moudle: )
android {
...
dataBinding {
enabled = true
}
}
그 후 dataBinding을 사용하는 xml의 최상위 계층은 <layout>으로 구성되어야 합니다.
activity_main.xml
<!-- 최상위 계층을 layout으로 적용 -->
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".MainActivity">
...
</layout>
여기까지 작업 진행이 완료되었다면
"ActivityMainBinding" 이름으로 dataBinding Class가 자동으로 생성됩니다.
private lateinit var binding: ActivityMainBinding
위와 같이 ActivityMainBinding 자료형으로 변수 선언 시
이미 자동으로 생성된 ActivityMainBinding Class가 존재하기 때문에
에러 없이 빌드 가능합니다.
( activity_main.xml에서 dataBinding을 적용했기 때문에
ActivityMainBinding Class가 자동으로 생성되었습니다.
만약 activity_intro.xml에서 dataBinding을 적용한다면
ActivityIntroBinding Class가 생성될 것입니다. )
MainActivity.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)
...
}
...
}
Activity에서 기존의 setContentView() 함수를 제거하고
DataBindingUtil.setContentView()로 교체합니다.
🎉 축하드립니다.
여기까지 완료하셨다면
드디어 dataBinding을 사용할 준비가 끝났습니다.
위에 선언해둔 binding을 사용하여 xml View에 직접적으로 접근이 가능합니다.
binding. 이후 xml에 선언해둔 View id 값을 작성하면
친절하게 자동완성으로 찾고자 하는 뷰 이름을 노출시켜 줍니다.
🧑💻 Binding 활용
자 이제 DataBinding을 활용하여 재밌는 기능을 확인해보겠습니다.
xml에서도 변수 선언이 가능하다는 사실 알고 계셨나요? 🧐🧐
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="activity"
type="kiu.dev.my_calculator.MainActivity" />
<variable
name="message"
type="String" />
<variable
name="isTrue"
type="Boolean" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
...
<TextView
...
android:text="@{message}"/>
<androidx.appcompat.widget.AppCompatButton
...
android:onClick="@{activity::onClickEvents}"/>
</layout>
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
binding.isTrue = versionData.isTrue()
binding.message = versionData.getVersion()
위와 같이 <layout> 태그 아래 <variable>을 이용하여 선언이 가능합니다.
이때 variable의 type 형태는 class, String, Integer, Boolean 등
기존 변수 선언 때 자료형을 정해주는 것과 같습니다.
기본 사용법은 다음과 같습니다. 🧑💻🧑💻
android:text="@{변수명}"
변수가 Class 변수라면
android:text="@{Class변수명.함수명}"
ex)
Class FindText() {
fun getText(): String {
return "FindText Str"
}
}
<variable
name="find"
type="...FindText"/>
android:text="@{find.getText()}"
삼항 연산자도 활용 가능합니다.
android:visibility="@{isTrue ? View.VISIBLE : View.GONE}"
클릭 이벤트에 대한 처리도 바로 가능합니다.
android:onClick="@{activity::onClickEvents}"
MainActivity.kt
fun onClickEvents(v: View) {
when(v.id) {
R.id.btn_click -> {
Log.d("TestLog", "MainActivity btn_click onClickEvents")
}
}
}
onClickEvents의 파라미터로 View 해당 뷰의 값이 들어오고
v.id 값으로 어떤 뷰의 클릭 이벤트 인지 구분하여 처리 가능합니다.
Kotlin에서 ::(더블 콜론)은 Reflection이라고 하며
더 자세한 내용은 따로 정리하여 올리도록 하겠습니다.
(요즘 글 하나 작성하기가 너무 힘드네요 ... 🥲)
✔️ Binding Adapter 사용법
Binding Adapter는 xml View의 특정 속성 값이 적용되었을 때
미리 정의해둔 로직을 실행시켜줍니다.
예시 소스를 한번 보시죠! 👀
(역시 말로만 사람을 이해시키는 건 어려운 일이죠...)
BindingAdapter.kt
object BindingAdapter {
@BindingAdapter("app:bindText")
@JvmStatic
fun setTextView(view: TextView, str: String) {
view.text = "version : $str"
}
}
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val versionData by lazy {
AppVersion("1.0.0")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.version = versionData.copy()
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="version"
type="kiu.dev.my_calculator.data.AppVersion" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout>
<TextView
...
app:bindText="@{version.version}"/>
...
</androidx.constraintlayout.widget.ConstraintLayout>
Binding Adapter와 Glide 라이브러리를 이용하면
ImageView를 더 간단하게 사용 가능합니다.
@BindingAdapter("app:imgUrl")
@JvmStatic
fun loadImageUrl(view: ImageView, url: String?) {
url?.let {
Glide.with(view.context)
.load(url)
.fitCenter()
.into(view)
}
}
여기서 잠깐! 🤔🤔
Binding Adapter는 꼭 xml 속성 값을 하나만 받을 수 있을까?
작업을 하다 보면 생각보다 여러 가지 Data들을 조합하거나
여러가지 조건들이 필요합니다.
@BindingAdapter("app:setVersion", "app:setStr", requireAll = false)
@JvmStatic
fun setTextView(view: TextView, version: String? = "", str: String? = "") {
view.text = "version : $version , $str"
}
위와 같이 두 가지 이상의 xml 속성 값으로 파라미터를 받을 수 있고
requireAll 속성 값을 추가하여 모든 속성 값들이 반드시 모두 필요한지 정의합니다.
여기까지 저의 긴 글을 읽어주셔서 감사합니다.
제가 습관적으로 코딩을 하는 그날까지 습관적으로 코딩을 하기 위해 글 작성을 꾸준하게 해보겠습니다.
'Android > 스터디 노트' 카테고리의 다른 글
[Android] 내가 만든앱, 내가 등록한다 - Google Play Store 개발자 계정 만들기 (0) | 2023.05.23 |
---|---|
Android13(SDK33) 이미지 및 사진 권한 (READ_EXTERNAL_STORAGE, READ_MEDIA_IMAGES) (12) | 2023.01.13 |
Android Deep Link 설정 및 adb 테스트 방법 (0) | 2022.11.18 |
Android PhotoPicker 권한 없이 갤러리에서 이미지 가져오기/이미지 다중 선택 (0) | 2022.11.15 |
Android 13 Notification Permission 알림 권한 띄우기. (8) | 2022.11.08 |
최근댓글