📱 Android

[Android] Jetpack Architecture #1 DataBinding

콩드로이드 2022. 6. 5. 14:28

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)?" />

 

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

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