본문 바로가기

Android/Jetpack, Clean Architecture

[안드로이드/Android] Databinding 사용하기

Databinding 사용한 예시를 만들기 전에 findViewByid의 작동 방식을 알아보고 가겠습니다.

 

목차

 

 

findViewByid 작동 방식과 문제점

우리가 뷰에 대한 참조를 얻기 위해서 findViewByid() 함수를 사용할 때마다 안드로이드 시스템은 런타임 중에 뷰 구조를(view hierarchy) 살펴보고 원하는 뷰를 찾아내는 작업을 합니다.

규모가 큰 앱의 경우 레이아웃이 많고 수 백개의 뷰가 있을 수 있습니다.

그럼 한 화면을 보여줄 때 안드로이드 시스템은 수 백번 뷰 구조를 보는 작업이 필요합니다.

-> 규모가 큰 앱의 경우 안드로이드 시스템에서 뷰를 참조하기 위한 많은 작업이 필요합니다.

 

적어도 오늘 날의 모바일 폰 시장에서 적어도 60Hz의 화면 재생 빈도(refresh frequency)를 가집니다.

화면 재생 빈도는 화면이 1초에 얼마큼 비추는지를 나타내는 값입니다.

즉 디스플레이가 초당 60회의 프레임을 나타낼 수 있습니다.

16밀리 초 마다 스크린을 다시 만듭니다..

안드로이드 시스템은 16밀리 초 안에 뷰의 구조를 살펴봐야 합니다.

몇몇 고급 사양의 폰들은 90Hz, 120Hz의 화면 재생 빈도(refresh frequency)를 가진다.

-> 기기 성능의 고도화로 인해 안드로이드 시스템은 뷰를 다시 만드는 데 더 적은 시간을 얻습니다.

 

결론 :  findViewByid 함수를 통해서 런타임 중에 뷰를 반복해서 살펴보는 것은 좋지 않습니다. 규모가 큰 앱의 경우 앱의 성능을 감소시킵니다.

 

 

findViewByid 소스 코드 분석

findViewByid의 소스 코드를 분석해서 성능 상에 영향을 미칠 수 있는 부분을 찾아보겠습니다.

public final View findViewById(int id) {
	if (id < 0) {
		return null;
	}
	return findViewTraversal(id);
}


findViewByid 함수를 보시면 id가 0 이상인 경우 즉 유효한 경우에 `findViewTraversal` 을 호출 합니다.

 

@Override
protected View findViewTraversal(int id) {
	if (id == mID) {
		return this;
	}
	final View[] where = mChildren;
	final int len = mChildrenCount;
	for (int i = 0; i < len; i++) {
		View v = where[i];
		if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
			v = v.findViewById(id);
			if (v != null) {
				return v;
			}
		}
	}
	return null;
}

findViewTraversal을 보시면 전달된 id가 ViewGroup의 ID와 같은지 여부를 확인하고 같은 경우에 자기 자신을 반환하고 아닌 경우 자기 자신이 가진 Child View에 대해 루프를 돌려 각 Child View에 findViewById를 호출하고 있습니다.

그렇다면 만약 ViewGroup안에 Child View가 100개가 있고 그 해당 뷰들을 찾아 넘길려면 최소 100번의 loop를 돌게됩니다.

이 부분에서 모든 뷰들을 불필요하게 확인하는 작업이 발생합니다.

 

DataBinding 작동방식

우리는 레이아웃에 속한 각각 뷰에 대한 참조를 가지는 binding 객체를 생성합니다.

binding 객체가 생성됐을 때 앱의 모든 컴포넌트들은 binding 객체를 통해서 뷰를 접근할 수 있습니다.

이 방법은 런타임 중에 뷰를 반복해서 살펴보지 않습니다.

 

findViewByid에 비해 Databinding이 가지는 이점

앱 성능을 향상시킴

findViewByid를 제거함으로써 코드를 더 간결하게 한다.

이는 코드를 읽고 유지 보수하는 게 더 수월해진다.

컴파일하는 도중에 에러를 발견할 수 있다.

findViewByid는 런타임 중에 발생하지만 Databinding은 컴파일 시 에러를 인지한다.

그러므로 에러가 있을 경우 사용자가 앱 사용 중에 에러를 마주치는 것을 방지할 수 있다.

 

사용법

gradle에 databinding 설정하기 (enable databinding)

Android Studio version 4.1 이상 버전의 경우 다음과 같이 추가합니다.

android {
 	...
	buildFeatures {
        dataBinding true
    }
}

Android Studio version 4.1 이전 버전의 경우 다음과 같이 추가합니다.

 
 android {
 	...
   dataBinding{
          enabled = true
   }
}

 

 

 

레이아웃 xml 파일을 layout 태그로 감쌉니다.

<?xml version="1.0" encoding="utf-8"?>
<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">

	 ...

 

 

binding 객체를 생성하고 사용합니다.

data binding 라이브러리는 레이아웃 파일 이름을 참고해 binding 객체를 생성합니다.

_(underscore)를 제거하고, 대문자를 추가하고 뒤에 Binding을 추가합니다.

예시) activity_main → ActivityMainBinding

 private lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
    }

 

객체를 사용한 Databinding

실제 앱은 로컬 디비나 API를 통해 가져온 데이터를 뷰에 보여주는 경우가 많습니다.

이런 경우 databinding을 통해 객체가 가진  데이터를 레이아웃 파일에서 넣을 수 있습니다.

 

데이터 클래스를 만듭니다.

data class Person (
    var id:Int,
    var name:String,
    var email:String
)

layout 태그 안에 다음과 같이 variable 태그를 사용해 레이아웃 파일에서 사용할 데이터를 정의합니다.

값은 @{}를 통해 참조할 수 있습니다.

<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">

    <data>
        <variable
            name="person"
            type="com.example.databindingex.Person" />
    </data>
    
    	
        <TextView
        	android:text="@{person.name}"
            .../>

 

앱을 실행하면 다음과 같이 나옵니다.

 

코틀린의 apply scope 함수를 사용함으로써 중복된 코드를 줄일 수 있습니다.

binding.apply {
   nameText.text =  "Hello!"
}

 

참고 : developer.android.com/topic/libraries/data-binding/start?hl=en

 

시작하기  |  Android 개발자  |  Android Developers

Android 스튜디오의 데이터 결합 코드 지원을 비롯하여 개발 환경에서 데이터 결합 라이브러리를 함께 사용하도록 준비하는 방법을 자세히 알아봅니다. 데이터 결합 라이브러리는 유연성과 광범

developer.android.com

 

전체 소스 : github.com/keepseung/Android-Blog-Source

 

keepseung/Android-Blog-Source

https://develop-writing.tistory.com/ 에서 제공하는 예제. Contribute to keepseung/Android-Blog-Source development by creating an account on GitHub.

github.com