본문 바로가기

[Android] DataBinding #1 - 기본

DataBinding #1 - 기본

 

 

Index

 

 

 

DataBinding ?

  • 기본적으로 앱을 개발할 때, 액티비티에 뷰를 바인딩하여 액티비티가 뷰를 조작하는 방식으로 사용
Button button1 = findViewById(R.id.button1)	// View를 바인딩(인스턴스화)
Button button2 = findViewById(R.id.button2)
...
...
Button button10 = findViewById(R.id.button10)

: 뷰를 바인딩하는 findViewById()가 조작할 뷰의 개수만큼 많이 늘어나고,

뷰의 UI Update Logic이 많이 생기면서 Activity가 무거워지고 책임이 늘어나게 됩니다 

  • 데이터바인딩은 XML레이아웃에 데이터를 바인딩해서 xml레이아웃이 View를 조작하므로,

    UI 컨트롤러(Activity/Fragment)에 불필요한 코드를 줄이는 방법 (MVVM 패턴 구현에 주로 사용)

  • DataBinding 장점

  1. findViewById() 사용 X (binding 객체를 통해 view 바로 접근가능)

  2. RecyclerView 사용 시 각각의 item들을 일일이 set하지 않아도 알아서 xml에서 처리 가능

  3. Observable을 이용해 실시간으로 데이터 변경 시 View를 Update 가능

 

 

사용방법

  1. Gradle 설정
  2. POJO (Model)
  3. XML 수정
  4. DataBinding
  5. Click 이벤트

 

 

데이터바인딩 라이브러리 최소사양

  • Support library : Android 2.1 (API 7) 이상
  • Android Plugin for Gradle : 1.5.0-alpha 이상
  • Android Studio : 1.3 이상

 

1. Gradle 설정

: build.gradle(Moudle: app) 내부 android { .. } 태그 사이에 아래 코드를 추가 (위치는 상관없습니다)

dataBinding {		// dataBinding 설정을 추가
    enabled = true	// enabled = true, 사용설정
}


+ Kotlin 설정

    : plugin: 'kotlin-kapt' 추가 + databinding compiler 추가 (Compiler버전은 본인 Gradle버전과 동일하게 설정) 

apply plugin: 'kotlin-kapt'		// plugin 추가
...

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    dataBinding {           /* DataBinding 사용 설정 */
        enabled = true
    }
    ...
}
dependencies {
	...
    kapt 'com.android.databinding:compiler:$본인Gradle버전' // gradle버전 3.5.3을 말함
}

Kotlin Gradle 설정

 

 

2. POJO (Model) 클래스 생성

public class User {
    private final String Name;
    private final int age;

    public User(String name, int age) {
        Name = name;
        this.age = age;
    }

    public String getName() {
        return Name;
    }

    public int getAge() {
        return age;
    }
}
  • User클래스에는 2개의 Getter메서드가 존재하는데 이 2개의 Getter메서드는

    XML에서 @{user.age} = getAge(), @{user.name} = getName() 으로 엑세스됩니다

 

 

3. XML 수정

: xml레이아웃을 <layout></layout> 태그로 감싸기

 

손쉽게 <layout></layout> 태그로 감싸는 방법

: 이미 선언된 Layout에서 "[Alt]+Enter"를 누르면 나오는 "Convert to data binding layout" 클릭 

: 자동으로 Root Layout을 <layout></layout>으로 변경해줍니다


<data></data> 태그사이에 <variable>태그를 사용하면 해당 xml내부에서 사용할 수 있는 변수 할당

<data> 태그로 선언한 변수는 "@{ }" 구문을 이용해서 VIew의 속성값에 대입하여 사용할 수 있습니다

 

 

 

4. DataBinding (데이터 바인딩 JAVA)

: DataBinding클래스는 xml레이아웃 파일 이름을 기준으로 자동 생성

xml레이아웃 파일 파스칼 표기법으로 변환 + "Binding" 접미사 추가

ex) activity_main.xml -> ActivityMainBinding.class

DataBinding 클래스명 Custom 방법

: <data>태그class 속성을 이용해서 Binding클래스 이름을 Custom

<data class="CustomName">

     ......

</data>

Binding 클래스이름 Custom

 

DataBinding 데이터바인딩

 

  • DataBindingUtil.setContentView(activity, layoutId) : DataBinding의 XML레이아웃 인플레이션 함수

      * setContentView(layoutId) : 기존의 XML레이아웃 인플레이션 함수

  • binding.setActivity() : XML 변수 "activity" 설정 (파라미터 - MainAcitivty)
  • binding.setUser() : XML 내부 변수 "user"  설정 (파라미터 - User)

     : setXXX() 형식의 XML파일내부 변수의 Setter 메서드를 자동으로 생성해줌

  • ActivityMainBinding : <layout></layout>으로 감싸진 XML의 Binding 클래스를 자동으로 생성해줌

     : DataBinding 클래스는 XML파일명(activity_main) + "Binding" 으로 자동으로 생성

 

5. 클릭 이벤트 (Click Event)

버튼 클릭 시 실행할 함수

public void onClickToast(View view) {
    count++;
    Toast.makeText(this, "Click count "+count, Toast.LENGTH_SHORT).show();
}


activity_main.xml

<data>
    <variable
    	name="activity"		// MainActivity Type의 변수 activity 선언
        type="com.jjj.myapplication.MainActivity" />
</data>

<Button
    ...
    android:onClick="@{activity::onClickToast}"		// activity변수 내부의 onClickToast() 함수실행
/>

 

MainActivity.java - XML activity변수 할당

ActivityMainBinding binding;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setActivity(this);
}

 

  • 'XML' android:onClick="@{activity::onClickToast}" : XML변수 activity 내부의 onClickToast 함수 실행을 의미
  • 만약 위의 기능을 기존의 Java로 구현했다면 일반적으로 아래와 같이 구현 

// 기본
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        onClickToast(view);
    }
});

public void onClickToast(View view) {
    count++;
    Toast.makeText(this, "Click count "+count, Toast.LENGTH_SHORT).show();
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
// View.OnClickListener를 Implement한 경우

Button button = findViewById(R.id.button);
button.setOnClickListener(this);

@Override
public void onClick(View view) {
    onClickToast(view);
}

public void onClickToast(View view) {
    count++;
    Toast.makeText(this, "Click count "+count, Toast.LENGTH_SHORT).show();
}

 

 

식 언어

  • 공통

수학 + - / * %

  • 수학 +, -, *, /(몫), %(나머지)
  • 문자열 연결 +
  • 논리 && (AND), || (OR)
  • 이항 & | ^
  • 단항 **+ - ! ~**
  • 시프트 >>, >>>, <<
  • 비교 ==, >, <, >=, <=
  • instanceOf
  • 그룹화 ()
  • 리터럴 - 문자, 문자열, 숫자, null
  • 형변환
  • 메서드 호출
  • 필드 엑세스
  • 배열 엑세스 []
  • 삼항 연산자 ?;
// 수학 연산자 +
android:text="@{String.valueOf(index + 1)}"

// 삼항 연산자 true = View.GONE / false = View.VISIBLE
android:visibility="@{age < 13 ? View.GONE : View.VISIBLE}"

// 문자열 연결 +
android:transitionName='@{"image_" + id}'

 

  • 연산 누락

Java에서 사용 가능한 식 / 구문에서 몇 가지 연산이 누락됨

  • this
  • super
  • new
  • 명시적 일반 호출

 

  • null 병합 연산자

null 병합 연산자는 왼쪽 피연산자가 null이 아니면 왼쪽 / null이면 오른쪽 피연산자를 선택

// user의 displayName 필드가 null이 아니면 왼쪽(displayName) / null이면 오른쪽(lastName)
android:text="@{user.displayName ?? user.lastName}"

// 동일한 의미의 표시
android:text="@{user.displayName != null ? user.displayName : user.lastName}"

 

  • 속성 참조

식이 클래스의 한 속성을 참조할 때 사용 Field, getter, ObservableField에 똑같이 적용

// getter = user.getLastName(), ObservableField = user.lastName.get() 의미
android:text="@{user.lastName}"

android:text="@{user.lastName]" 의미는 getter, ObservableField에 똑같이 적용됩니다

user가 POJO 인스턴스라면 user.getLastName() 의 의미와 동일

user 내부 lastName이 Field(필드) 속성이라면 user.lastName.get() 의 의미와 동일  

 

  • 문자열 리터럴

특성 값을 작은 따옴표('')로 묶어서 사용하면 식 내부에서 큰 따옴표를 사용할 수 있습니다

특성 값을 큰 따옴표("")로 묶을 경우 문자열 리터럴에는 '또는 `중 하나를 사용해야 합니다

// 특성 값을 작은 따옴표('')로 묶은 경우 식(@{}) 내부에서 큰 따옴표("")를 사용가능
android:text='@{map["firstName"]}'
or

// 특성 값을 큰 따옴표("")로 묶은 경우 작은 따옴표(') 또는 `(1옆에 있는물결) 중 하나 사용 가능
android:text="@{map[`firstName`]}"		// 1옆의 물결문자
android:text="@{map['firstName']}"		// 작은 따옴표

 

  • 리소스

일반적인 구문을 사용하는 식의 일부로 리소스에 Access 할 수 있음

// 일부로 리소스에 액세스할 수 있음, @dimen 리소스 접근
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

// 매개변수를 제공하여 형식 문자열과 복수형을 평가할 수 있음
android:text="@{@string/nameFormat(firstName, lastName)}"
android:text="@{@plurals/banana(bananaCount)}"

// 복수형이 여러 매개변수를 취할 때는 모든 매개변수가 전달되어야 함
  Have an orange
  Have %d oranges

android:text="@{@plurals/orange(orangeCount, orangeCount)}"

 

형식 일반적인 참조 식 참조
String[] @array @stringArray
int[] @array @intArray
TypedArray @array @typedArray
Animator @animator @animator
StateListAnimator @animator @animator
color (int) @color @color
colorStateList @color @colorStateList