[Android] 안드로이드 뷰 바인딩(View binding) 기초 & 예제 코드 총정리 : DataBinding은?
안드로이드스튜디오를 최신버전으로 업그레이드 후 신규 프로젝트를 생성하면 기존에 보지 못했던 코드들이 자동 생성되는 것을 확인할 수 있다.
안드로이드스튜디오 3.5 버전까지는 개발자들이 findViewById를 사용했었다. 그리고 개발자들은 Butter knife라는 라이브러리나 extension을 이용해서 불편함을 해결했다. 이 후 안드로이드스튜디오 3.6 버전에서 이를 대체할 수 있는 view binding이 나왔다.
View Binding 사용한 방법
private ActivityMainBinding viewBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(viewBinding.getRoot());
viewBinding.textView.setText(userProfile.name);
viewBinding.btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
}
});
// 람다식 -> : JDK 1.8버전 이상에서 사용가능
viewBinding.btn.setOnClickListener(v -> Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show());
//롱클릭 람다식 표기법
viewBinding.btn.setOnLongClickListener( v-> {
Toast.makeText(this, "hello", Toast.LENGTH_SHORT).show();
return true;
});
}
inflate는 xml에 있는 뷰를 객체화해준다고 생각하면 될 것이다.
기존 findViewById 방법
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
TextView textView = findViewById(R.id.text_view);
textView.setText("Hello");
}
바인딩 클래스 명명 규칙(자동)
View Binding
은 안드로이드 아키텍쳐 구성요소 중 하나로 뷰와 상호작용 하는 코드를 쉽게 작성할 수 있게 해준다. xml과 연결되는 바인딩 클래스가 자동으로 생성되고 그 클래스의 멤버로 xml의 ID를 가진 모든 뷰를 참조하는
참조 변수가 있다.
액티비티 레이아웃 파일명과 자동으로 만들어지는 바인딩 클래스명 예시는 다음과 같다.
//액티비티 레이아웃 파일명과 자동으로 만들어지는 바인딩 클래스명
activity_main.xml -> ActivityMainBinding
activity_second.xml -> ActivitySecondBinding
프레그먼트 레이아웃 파일명과 자동으로 만들어지는 바인딩 클래스명
fragment_home.xml -> FragmentHomeBinding
fragment_xxxx.xml -> FragmentXxxxBinding
//리사이클러뷰(아답터뷰)의 아이템 레이아웃 파일명과 자동으로 만들어지는 바인딩 클래스명
recycler_item.xml -> RecyclerItemBinding
findViewById
에는 몇가지 문제점이 있는데, 실수로 없는 id를 사용하면 NULL 오류가 발생하고, 뷰의 타입을 잘못 적으면 오류가 발생하며, 코드가 많아진다.
뷰 바인딩 사용을 위한 기본 설정
build.gradle 파일에 아래와 같이 설정해주고, sync를 클릭하면 되는데, 안드로이드 스튜디오가 최신버전이라면 default 값으로 설정되어 있다.
// 안드로이드 스튜디오 4.0 이상
android {
...
buildFeatures {
viewBinding true
}
}
// 안드로이드 스튜디오 3.6 ~ 4.0
android {
...
viewBinding {
enabled true
}
}
Fragment 뷰 바인딩 예제
public class HomeFragment extends Fragment {
private FragmentHomeBinding binding;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
new ViewModelProvider(this).get(HomeViewModel.class);
binding = FragmentHomeBinding.inflate(inflater, container, false);
View root = binding.getRoot();
final TextView baseDate = binding.baseDateText;
baseDate.setText("");
// final Button addbtn = binding.addBtn;
// homeViewModel.getText().observe(getViewLifecycleOwner(), addbtn::setText);
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
프래그먼트는 위와 사용되며, 차이점은 onDestroyView에서 binding에 null을 코딩해주어야 한다. 그 이유는 프래그먼트는 뷰보다 더 오래 살아남아 있기 때문이다.
Fragments outlive their views. Make sure you clean up any references to the binding class instance in the fragment's onDestroyView() method.
DataBinding (view binding + data binding) : 뷰결합 + 데이터 결합 아키텍쳐
android {
.....
//Android Studio 4.0 버전 이상일때,
buildFeatures {
dataBinding = true
}
//Android Studio 4.0 버전 미만일때,
dataBinding {
enabled= true
}
}
데이터 바인딩의 사용설정을 해주면 뷰바인딩과 마찬가지로 레이아웃 xml 파일과 연결되어 자동으로 바인딩 클래스가 생성된다. 차이점은 Data Binding의 root는 <layout>을 최상단에 추가해주어야 하고, <data> 요소가 추가해준다.
# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- 레이아웃뷰와 바인딩할 데이터들 명칭과 클래스지정 : 데이터바인딩으로 연결할 testVo 클래스를 이 레이아웃에서 testVo 라는 이름으로 참조하여 사용하겠다는 의미-->
<data>
<variable name="testVo"
type="com.test.common.TestVo" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@{String.valueOf(testVo.age)}"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="북마크"
android:checked="@{testVo.isBooked}"/>
</LinearLayout>
</layout>
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setTestVo(new TestVo("HONGGILDONG", 30, true));
}
}
public class TestVo{
String name;
int age;
boolean isBooked;
//생성자
public TestVo(String name, int age, boolean isBooked){
this.name = name;
this.age = age;
this.isBooked = isBooked;
}
}
[reference]
https://kitesoft.tistory.com/118