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

My name is Taehwan Kwon. I have developed Android for 6 years and blog has been active for eight years.

Comments