💡 / 키를 눌러 빠르게 검색하세요!

ButterKnife/findViewById 대신 Kotlin android extensions 사용하기

본문

Kotlin에서는 ButterKnife와 findViewById을 사용하지 않아도 됩니다.

Kotlin에서는 간단하게 kotlin Extensions을 사용할 수 있습니다.

우선 적용하지 않고 일반적인 코드는 아래와 같습니다.

findViewById를 매번 해야 하고, 귀찮습니다.

적용하는 방법도 여러 가지가 있을 수 있습니다.

class ImageFragment : Fragment(), ImageContract.View {

    private val rootContainer by lazy {
        activity.findViewById(R.id.root_container) as CoordinatorLayout
    }

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        // 또는 아래와 같이
        val rootContainer = activity.findViewById(R.id.root_container) as CoordinatorLayout
    }
}

그래서 나온 것이 ButterKnife입니다. 아래와 같이 어노테이션을 이용하여 간단하게 사용이 가능합니다.

Data Binding을 쓰지 않는다면 ButterKnife이 아직은 최고라고 할 수 있습니다.

public class PhotoViewActivity extends AppCompatActivity {

    @BindView(R.id.toolbar) Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ButterKnife 사용
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);
    }
}


Kotlin android extensions 적용하기

Kotlin을 메인 언어로 사용하는데 있어서 어떤 걸 쓰는 게 좋을까요?

data binding도 사용은 가능하고, findViewById로도 사용할 수 있습니다.

하지만 Kotlin에서는 아래와 같이 1줄만 추가해주면 extensions을 사용할 수 있는 kotlin-android-extensions이 제공됩니다.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.ext.kotlin_version"
}

당연히 kotlin 적용은 되어 있는 상태에서 활용이 가능합니다.

그리고 위에서 적용했던 코드에 android-extensions을 적용하면 아래와 같습니다.

그냥 layout에서 정의한 android:id="@+id/text"를 직접 사용할 수 있습니다.

ButterKnife에서 적용했던 것처럼 ButterKnife.bind()도 불필요하고, findViewById도 불필요합니다.

그냥 바로 android:id="@+id/text"text를 통해 바로 접근할 수 이는 코드가 만들어집니다.

import kotlinx.android.synthetic.main.activity_image_sample.*
import kotlinx.android.synthetic.main.fragment_image_sample.*

class ImageFragment : Fragment(), ImageContract.View {

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        with (activity) {
            root_container.visibility = View.GONE
        }
        recycler_image.visibility = View.GONE
    }
}

하지만 이때 import가 추가됩니다.

import kotlinx.android.synthetic.main.activity_image_sample.*
import kotlinx.android.synthetic.main.fragment_image_sample.*

import에는 kotlinx.android.synthetic.main까지는 공통으로 적용하고, 이후에는 layout의 이름을 사용합니다.

레이아웃 이름이 activity_image_sample이면 위와 같이 적용되고 끝에 .*이 추가됩니다.

activity_image_sample에 포함하는 모든 데이터를 불러와서 쓸 수 있다는 말이 됩니다.


이는 자동으로 import 하게 됩니다.

하지만 모든 레이아웃이 이렇게 적용되면 좋겠지만 그렇지 않습니다.

그래서 적용하는 방법이 2가지 정도가 있습니다.

일반적으로는 with () {}을 이용해서 처리가 가능합니다.

with 안에는 layout의 이름 또는 최상위 접근자를 추가해도 좋습니다.

예를 들면 아래와 같은 코드가 됩니다.

with (activity) {
  root_container.visibility = View.GONE
}

만약 직접 만든 layout에 null 일 가능성이 있다면?

아래와 같이 작업해도 좋습니다.

activity?.apply {
    root_container.visibility = View.GONE
}

이런 코드들은 알아서 findViewById을 생성해줍니다.

그만큼 편리하게 사용이 가능하지만 커스텀 뷰나 ViewHolder에서는 아래와 같은 코드를 함께 사용해야 해서 조금은 분편합니다.

with (itemView) {
  root_container.visibility = View.GONE
}

// Null 발생을 대처하기 위해서 아래와 같이 사용한다
itemView?.run {
    root_container.visibility = View.GONE
}


마무리

Kotlin에서는 ButterKnife는 필요하지 않습니다.

찾아보면 jakewharton이 작업했던 KotterKnife도 있긴 합니다.

하지만 Kotlin extensions이 있기에 초기에만 배포하고 이후에는 하지 않았습니다. kotlin extensions이 너무 편하기 때문이죠.

kotlin 적용 및 kotlin extensions만 적용하더라도 개발 속도를 향상시킬 수 있습니다.

감사합니다.



About Taehwan

안드로이드 개발 12년차, 모바일앱 개발자 권태환입니다. 코드와 아키텍처, 그리고 개발 문화에 관심이 많습니다. GDG Korea Android와 DroidKnights에서 개발자 커뮤니티를 함께 만들어가고 있습니다.

Comments

테오 AI powered by Gemini 2.5 Flash
🤖
안녕하세요! 테오입니다. 😊
이 블로그의 모든 포스트를 학습했어요.
Android, Kotlin, 개발 관련 궁금한 점을 물어보세요!