findViewById 함수가 Boilerplate code 이슈가 있다는 것은 대부분의 개발자들이 알고 있을 것이다.
그래서 이를 해결하기 위한 다양한 라이브러리들이 존재한다.
그 중 대표적인 두 가지에 대해서 포스팅하려고 한다.
Kotlin Android Extensions (이하 KAE)
한 줄만 추가해주면 쉽게 사용가능하다.
1. build.gradle(Module: app) 수정
...
dependencies {
...
implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.ext.kotlin_version"
}
2. 사용 방법
만약 android:id = "@+id/bt_on"
라는 아이디를 접근하기 위해서는,
bt_on.setText(...)
bt_on.setOnClickListener(...)
이런식으로 바로 사용 가능하다.
대신에 import문이 추가로 생성되는 것을 볼 수 있다.
🔔 [2020-10-07 추가]
안드로이드 4.1 버전에서는 더 이상 KAE를 기본 제공하지 않는다고 한다.
관련해서 태환님 블로그 글에 자세히 나와 있으니, 읽어보는게 좋겠다.
View Binding
한 줄은 아니지만 쉽게 사용 가능하다.
1. build.gradle(Module: app)
android {
...
viewBinding {
enable = true
}
}
※ 만약 Android gradle plugin 버전이 4.0 이상이면 다음과 같이 사용해야 한다.
android {
...
buildFeatures {
viewBinding = true
}
}
바인딩 클래스를 생성하는 동안 레이아웃 파일을 무시하려면 다음 설정을 추가한다.
<LinearLayout
...
tools:viewBindingIgnore="true">
...
</LinearLayout>
1.1 Troubleshooting
build.gradle 파일에 viewBinding 설정을 했는데, 다음과 같은 에러가 발생했다.
Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method viewBinding() for arguments [build_f2anc1ehzzonoo7anmgc2vftc$_run_closure1$_closure5@67825409] on object of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.
Gradle version이 낮아서 나타나는 문제였다. 버전을 3.6 이상으로 올려야 한다.
//build.gradle(Project:...)
buildscript {
ext.kotlin_version = '1.3.71' // 1.3.41 -> 1.3.71 변경
...
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' // 3.5 -> 3.6.3 변경
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // kotlin_version을 1.3.71로 바꿔야 한다고 경고 발생
}
}
이렇게 하면 위 에러는 해결된다.
2. 사용 방법
Data binding에서의 클래스 네이밍과 비슷하다(카멜 표기법). 예를 들어서 activity_main.xml
파일에 적용하기 위해서 생성되는 바인딩 클래스의 이름은 ActivityMainBinding
이다.
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.txtTitle.text("Title")
}
※ 참고로, Java에서는 다음과 같이 사용한다.
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.txtTest.setText("View binding test");
}
Kotlin Andrid Extensions vs. View binding
먼저 공통점을 얘기해보면, 앞서 얘기한 Boilerplate code 대응이 가능하다는 점(사실 StackOverflow 글을 보면 KAE가 더 좋다고 얘기한다.) , Null safety, Type safety하다는 점이다.
그래서 개발자의 생산성을 늘릴 수 있다.
차이점을 살펴보면,
- KAE는 kotlin만 사용 가능하지만. View binding은 Java, Kotlin 모두 사용 가능하다.
- 레이아웃 변경에 대해 적용할 때 KAE는 즉시 synthetic extensions로 translate되어서 바로 사용할 수 있다. 그에 반해 View binding은 프로젝트를 빌드해야 한다.
- 레이아웃을 잘 못 사용한 경우 KAE, View binding 모두 NullPointerException이 발생할 수 있다. 하지만 잘못된 Class 이름보다는 잘못된 Import 작업을 할 가능성이 더 높고, 레이아웃 파일이 Activity, Fragment, View의 이름을 따서 잘 명명된 경우에는 View binding이 더 우위를 점한다.
둘 다 나름의 특징이 있기 때문에, 무엇을 사용해야하는지는 각자 판단하면 된다.
다만, Java를 사용한다면, View binding은 기존에 사용하던 ButterKnife를 대체할 수 있겠다.
만약 Kotlin을 사용한다면, View binding과 KAE 모두 사용 가능하지만 개인적인 생각으로는 조금 더 사용하기에 간편한 KAE가 좋을 것 같다.
(근데, Data binding을 사용하는 유저들은 View binding을 좋아한다고 함)
참고
https://medium.com/kayvan-kaseb/android-jetpack-view-binding-4758c729ebe3
https://medium.com/@charlezz/view-binding-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-df3526d909a7
https://stackoverflow.com/questions/58351239/viewbinding-vs-kotlin-android-extensions-with-synthetic-views