본문 바로가기
📱 Android

[Android] Jetpack Architecture #1 DataBinding

by 콩드로이드 2022. 6. 5.

Jetpack 컴포넌트는  생산성을 높인 개발을 도우는 라이브러리로, 아래와 같은 특징이 있습니다 

 

   1. 애플리케이션 설계 권장사항을 따름

   2. 보일러 플레이트 코드 줄임

   3. 복잡한 작업들 간소 -> 중요 코드에만 집중

 

Jetpack 컴포넌트는 Foundation, Architecture, Behavior, User Interface 4개의 카테고리를 가지는데 그 중  Architecture에 대해서 알아보겠습니다

 

 


DataBinding

xml을 앱의 데이터와 결합할 수 있는 라이브러리

 

- findViewById 메소드를 호출할 필요가 없어 앱 성능이 향상, 메모리 누수 및 NPE를 방지할 수 있다

💬 호출할 필요가 없는 이유 ? 

     바인딩 클래스 내부에서 미리 findViewById를 호출하고 그 결과를 캐싱해두기 때문에

 

- View를 선언하고 데이터를 넣어주는 코드가 사라져서 보일러 많은 플레이트 코드가 줄어듭니다 

 

🔍 DataBinding 설정하기

설정하기 전 아래의 버전 이상이 필요합니다 
Android 4.0이상
Android Studio 1.5.0 이상 

 

build.gradle(app)

dataBinding {
    enabled = true
}

위와 같이 build.gradle에 선언합니다

 

이제 Databinding을 사용할 준비는 끝났습니다🏁

 

 

🔍 Binding 클래스 생성하기

xml에서 직접 데이터와 결합시키는 형태이다보니, 기존의 xml 파일과는 생김새가 조금 달라집니다

레이아웃의 변수와 뷰를 참조할 수 있는 Binding 클래스를 생성해보겠습니다 

 

xml 파일에서 가장 상위 레이아웃을 <layout>으로 감싸주면 자동으로 바인딩 클래스가 생성됩니다

이 때 클래스의 명은 xml파일명을 파스칼케이스로 변경 후 Binding이 붙은 형태가 됩니다 

ex) activity_main.xml  ▶️  ActivityMainBinding

<layout>
	<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    	android:layout_width="match_parent"
        android:layout_height="match_parent"
        orientation:="vertical"/>
</layout>

 

🔍 Binding 객체 생성

Binding 객체 생성에는 여러가지 방법이 있습니다

 

1. inflate()

  - 레이아웃 전개와 함께 객체를 선언

// in Activity 
val biding = ActivityMainBinding.inflate(layoutInflater)

// in Fragment
val binding = ActivityMainBinding.inflate(LayoutInflater.from(context), this, false)

 

2. bind()

  - 레이아웃이 전개된 후 바인딩할 경우 사용

val binding = ActivityMainBinding.bind(rootView)

 

3. DataBinding.Util

  - 바인딩 클래스의 이름을 미리 알지 못하는 경우 사용 

//use inflate
val binding = DataBindingUtil.inflate(
	layoutInflater,
    R.layout.activity_main,
    parent,
    attachToParent
 )
 
 //use bind
 val binding = DataBindingUtil.bind(rootView)

 

- DataBindingUtil내엔 setContentView 메서드가 포함되어 있어 activity의 setContentView를 대체할 수도 있습니다

binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

 

 

🔍 xml에 변수 선언하기

위에 말했던 것과 같이 DataBinding은 레이아웃 id를 선언하고 뷰에 접근할 필요 없이

xml에서 변수를 선언하고 변수에 값을 대입하는 것으로 뷰의 상태를 변화시킬 수 있습니다

 

이를 위해 xml에서 변수를 어떻게 선언하는지 알아보겠습니다 

 

변수선언은  <layout>태그 내의 <data>를 사용해야합니다 

<data>내에서 <variable>을 사용해 선언하고 싶은 변수를 선언합니다 

 

<variable>은 여러 개 선언이 가능하고 name(변수 이름), type(변수의 자료형) 속성을 가집니다 

<layout>
	<data>
    	<variable
        	name="tvTest"
           	type="String"/>
   	 </data>
</layout>

 

위와 같이 선언한 변수를 바인딩하려면 @{변수명} 을 사용합니다

<Textview
    android:id="@id/tvShow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{tvTest}" />

 

📌 만약, xml에서 아닌 binding 클래스에서 변수에 값을 대입하려면 setter메서드를 사용합니다 

xml에서 선언한 변수명에 set이 접두어로 붙은 메서드가 생성되어있습니다 

binding.setTvTest("Hello World")

 

또, 변수엔 원시형태가 아닌 POJO클래스도 선언이 가능합니다 

 

<layout>
	<data>
    	<variable
        	name="person"
           	type="POJO 클래스의 위치"/>
   	 </data>
</layout>

 

person 클래스에 getName 메서드가 있다고 가정했을 때, 

<Textview
    android:id="@id/tvShow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{person.getName}" />

 

View에 데이터를 할당하는 방식은 똑같고, variable 선언 시 type이 클래스의 위치가 들어간다는 차이점이 있습니다 

 


🔍 Binding 표현식

보다 유연한 사용을 위해 바인딩의 표현식에 간단히 알아보겠습니다 

바인딩은 지원하는 문법이 많으므로, 어떤 문법들을 지원하느지에 대해선 자세히 다루진 않겠습니다 

 

아래와 같이 연산자의 사용도 자유롭습니다 

android:visibility="@{num > 28 ? View.GONE:View.VISIBLE}"
android:text="@{person.getName ?? "empty"}

 

Collections 클래스들도 사용이 가능합니다 

⚠️ 주의할 점은 <는 &lt;로 이스케이핑이 필요합니다 

 

<import>는 참조하고싶은 클래스를 xml에 가져옵니다 

만약, 클래스의 이름이 동일하다면 <import>내에 alias메서드를 사용해 alias ="변경할 이름" 로 이름을 변경할 수 있습니다 

<data>
    <import type="android.util.SparseArray"/>
    <import type="java.util.List"/>
    <variable name="list" type="List&lt;String>"/>
    <variable name="sparse" type="SparseArray&lt;String>"/>
</data>
<Textview
    android:id="@id/tvShow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{list[index]}" />
    
 
 <Textview
    android:id="@id/tvShow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{sparse[index]}" />

 

 

🔍 Binding 이벤트

1. 메서드 참조

   Handler를 사용해 직접 바인딩, 메서드명과 매개변수가 반드시 일치해야함

class ListenerHandler {
	fun onClickTv(v : View) { }
}
<data>
	<variable name="listener" type="핸들러 클래스 위치"/>
</data>

<TextView
	android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@id/tvTest"
    android:onClick="@{listener.onClickTv}" />

 

2. Listener Binding

 - 반환 타입만 일치시켜도 가능

class Change {
	fun onChanged(task: Task, done: Boolean){}
}

<CheckBox
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onCheckedChanged="@{(cb, isChecked) ->
    change.onChanged(task, isChecked)?" />

 

여기까지 기본적인 사용법을 알아보았습니다

다음은 좀 더 심화된 사용법을 알아보겠습니다