Hello World!
TextView label = findViewById(R.id.textview);
label.setText("Hello World!");
findViewById(...)
안드로이드를 처음 배울 때 제일 많이 사용한 구문입니다. 그러나! 해당 구문은 레이아웃 파일이 커질수록, 찾는 요소가 많아질수록 비용이 커지기 때문에 사용하지 말아야 합니다...
내부적으로 findViewById(...)
구문은 다음과 같이 작용합니다. 안드로이드는 매번 findViewById(...)
구문이 호출될 때마다 레이아웃 파일 트리를 순회하며 해당하는 요소를 찾습니다. 그러니 레이아웃 파일이 많아지거나 찾는 요소가 많아질수록 시간이 늘어날 수 밖에 없는 구조이지요. 구글 엔지니어들은 Data Binding
기법을 통해 이러한 문제를 해결하였습니다.
Data Binding
Data Binding
의 컨셉은 단순합니다. 레이아웃 파일을 중개해주는 오브젝트를 만들어 관리하는 방법입니다. 액티비티 입장에서는 해당 오브젝트의 속성에 접근하듯 bindObj.textView
와 같은 방식으로 레이아웃의 요소에 접근할 수 있습니다.
Gradle Scripts
Data Binding
을 사용하기 위해서는 먼저 Gradle Scripts
에서 해당 기능을 활성화하여야 합니다. Gradle Scripts
는 백그라운드에서 프로젝트 구성을 위해 사용되며, 이 중 build.gradle
을 수정하여 JDK 버전을 설정하거나 라이브러리를 추가하는 등 프로젝트와 관련된 설정을 수행할 수 있습니다. build.gradle
은 Project, Module 두 개의 파일로 나뉘는데, build.gradle(Project: ...)
파일은 모든 서브 프로젝트, 모듈에 적용되는 최상위 빌드 파일이며, common configs
를 포함하여야 합니다. build.gradle(Module: ...)
은 해당 모듈에만 적용되는 구성 파일입니다.
데이터바인딩은 기타 모듈을 제외한, 어플리케이션에만 적용되어야 하므로, build.gradle(Module: ...)
에 적용하는 것이 맞습니다. build.gradle(Module: ...)
에 다음과 같이 추가합니다.
android {
...
buildFeatures {
dataBinding true
}
}
layout_file.xml
이제 다음과 같이 각 레이아웃 파일 내용을 <layout>
태그로 감싸줍니다. 이 과정에서 xml name space는 최상단 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">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/profileImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:contentDescription="@string/name"
app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView
android:id="@+id/name"
style="@style/name_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RooMedia" />
<TextView
android:id="@+id/hobbies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Playing Guitar, Drink Water, ..., etc" />
<Button
android:id="@+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HIDE" />
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>
LayoutActivity.java
위 두 과정을 마치면 이제 데이터 바인딩을 사용할 수 있습니다. 레이아웃 파일의 이름에 따라 데이터를 중개해주는 클래스가 생성됩니다. 레이아웃 파일 이름이 activity_main.xml
이었다면 ActivityMainBinding
과 같은 자료형이 생성되는 식으로, 모든 레이아웃 파일에 각각을 나타내는 클래스가 생성됩니다.
사용은 다음과 같이 할 수 있습니다. setContentView
부분에 변화가 생겼고, 이후에는 binding
멤버변수를 활용하여 이전과 동일하게 사용할 수 있습니다.
package com.roo_media_.helloandroidworld;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.View;
import com.roo_media_.helloandroidworld.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.toggleButton.setOnClickListener(this::toggleViews);
}
private void toggleViews(View view) {
int visibility;
String buttonText;
switch (binding.profileImage.getVisibility()) {
case View.VISIBLE:
visibility = View.GONE;
buttonText = "SHOW";
break;
default:
visibility = View.VISIBLE;
buttonText = "HIDE";
break;
}
binding.profileImage.setVisibility(visibility);
binding.name.setVisibility(visibility);
binding.hobbies.setVisibility(visibility);
binding.toggleButton.setText(buttonText);
}
}
Insert Data
데이터 바인딩은 위와 같은 기능 뿐만 아니라, 레이아웃 파일을 데이터와 연결하는 역할을 하기도 합니다. 이를 이용하면 데이터를 수정하면 레이아웃 값을 따로 바꾸지 않아도 수정됩니다. 먼저 Bio.java
파일을 만들어 다음과 같은 클래스를 생성합니다. Bio
클래스는 name, hobbies를 멤버변수로 가지며, getter, setter를 통해 값을 조작합니다.
package com.roo_media_.helloandroidworld;
public class Bio {
private String name;
private String hobbies;
public Bio() {
}
public Bio(String name, String hobbies) {
this.name = name;
this.hobbies = hobbies;
}
public String getName() {
return name;
}
public String getHobbies() {
return hobbies;
}
public void setName(String name) {
this.name = name;
}
public void setHobbies(String hobbies) {
this.hobbies = hobbies;
}
}
xml 파일에서는 이런 식으로 표현합니다.
<?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">
<data>
<variable
name="bio"
type="com.roo_media_.helloandroidworld.Bio" />
</data>
...
<TextView
android:id="@+id/name"
style="@style/name_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bio.name}"
tools:text="RooMedia" />
<TextView
android:id="@+id/hobbies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{bio.hobbies}"
tools:text="Playing Guitar, Drink Water, ..., etc" />
....
</layout>
연결을 위해 binding
에서 setter를 이용합니다.
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Bio bio = new Bio();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.toggleButton.setOnClickListener(this::toggleViews);
bio.setName("RooMedia");
bio.setHobbies("Playing Guitar, Drink Water, ..., etc");
binding.setBio(bio);
}
}
'Android' 카테고리의 다른 글
View Binding = findViewById 대체하는 방법, View Binding과 Data Binding 차이 (1) | 2021.02.08 |
---|---|
#Volley 로 안드로이드 앱에 #API #JSON 연결하기 (0) | 2021.02.02 |
Noti Alarm - 긴급 알람 앱 (2) | 2020.12.23 |
Jsoup Coroutine Warning: Inappropriate blocking method call - 안드로이드 이슈 12 (0) | 2020.05.10 |
안드로이드 개발자 사이트가 느리다.. (0) | 2020.04.29 |