Kotlin-Android-Extensions이 deprecated된 이유

blue·2021년 5월 18일
0

android

목록 보기
4/4
post-thumbnail

생겨난 이유

안드로이드 화면(액티비티)은 xml(레이아웃 파일)과 java(소스 파일)로 구성된다. xml에서 뷰들을 만들고, java에서 이벤트 처리를 구현한다.

java에서 xml 뷰들을 사용하려면 이들이 메모리에 올라와야 한다. 그래서 액티비티의 onCreate()에서 setContentView()를 한다(인플레이션).
그리고 객체를 찾을 때 findViewById() 메소드를 사용하게 된다.

여기서 findViewById()는 객체마다 작성해야 하기 때문에 만약 버튼이 100개라면 100번 모두 호출해야 된다는 문제가 생긴다.
이 부분을 개선하기 위해 과거에 ButterKnife 라이브러리가 생겨 많이 사용되었고, Kotlin Android Extensions, ViewBinding, DataBinding 등이 생겨났다.

Kotlin Android Extensions

장점

1. 간편성
build.gradle에 아래 코드를 추가만 해주면

plugins {
	...
    id 'kotlin-android-extensions'
}

소스 파일에서 추가 코드를 작성하지 않아도

import kotlinx.android.synthetic.main.activity_main.*
...

	override fun onCreate(savedInstanceState: Bundle?) {
		...
        	btn.text="Hello World"
            	...
      	}
  

이렇게 바로 가져와서 쓸 수 있다. import 역시 자동으로 알맞은 레이아웃 파일을 해준다.
따라서, 반복적인 findViewById() 사용을 줄인다.

2. 재사용성
KAE는 내부적인 캐싱을 통해 재사용성을 높인다.

단점

1. RecyclerView의 ViewHolder 사용 시 문제점
사실 findViewById()는 똑같은 코드를 계속 써줘야 한다는 귀찮음도 있지만, 해당 메소드를 자주 호출하면 성능 저하의 문제점도 있다. 그래서 ButterKnife나 바인딩 방식을 사용한 것이다. 그런데 RecyclerView에서 KAE를 쓰고 java로 디컴파일했더니 findViewById()를 쓰고 있었다.

Kotlin

class SearchAdapter : RecyclerView.Adapter<SearchAdapter.RepositoryHolder>() {

    private var items: MutableList<GithubRepo> = mutableListOf()

    ...

    override fun onBindViewHolder(holder: RepositoryHolder, position: Int) {
        items[position].let { repo ->

            with(holder.itemView) {

                // ImageView, TextView에 접근
                GlideApp.with(context)
                        .load(repo.owner.avatarUrl)
                        .placeholder(placeholder)
                        .into(ivItemRepositoryProfile)

                tvItemRepositoryName.text = repo.fullName
                tvItemRepositoryLanguage.text = if (TextUtils.isEmpty(repo.language))
                    context.getText(R.string.no_language_specified)
                else
                    repo.language

                setOnClickListener { listener?.onItemClick(repo) }
            }
        }
    }
    ...
}

Java로 디컴파일

public final class SearchAdapter extends Adapter {
   ...

   public void onBindViewHolder(@NotNull SearchAdapter.RepositoryHolder holder, int position) {
      Intrinsics.checkParameterIsNotNull(holder, "holder");
      Object var3 = this.items.get(position);
      GithubRepo repo = (GithubRepo)var3;
      View var5 = holder.itemView;

      // 캐시를 사용하지 않고 매번 findViewById() 메소드를 사용
      GlideApp.with(var5.getContext())
          .load(repo.getOwner().getAvatarUrl())
          .placeholder((Drawable)this.placeholder)
          .into((ImageView)var5.findViewById(id.ivItemRepositoryProfile));
      ((TextView)var5.findViewById(id.tvItemRepositoryName)).setText((CharSequence)repo.getFullName());
      ((TextView)var5.findViewById(id.tvItemRepositoryLanguage)).setText(TextUtils.isEmpty((CharSequence)repo.getLanguage())?var5.getContext().getText(2131623973):(CharSequence)repo.getLanguage());
      var5.setOnClickListener((OnClickListener)(new SearchAdapter$onBindViewHolder$$inlined$let$lambda$1(repo, this, holder)));
   }

   ...
}

2. 뷰가 동일한 id를 가지는 경우 애매성, 널 안정성
a.xml의 버튼 aa의 id를 btn이라 하고, b.xml의 버튼 bb의 id도 btn이라고 하자. 특정 액티비티에서 두 버튼을 호출한 후, a.xml에서 aa를 지워도 액티비티 소스 파일에는 오류가 뜨지 않는다.
극단적인 예시일 수도 있지만, 이로 인해 나중에 더 큰 이슈가 생길 수도 있다.

3. Kotlin에서만 동작
아무리 Kotlin을 서포트한다지만 태초에는 Java가 있었다 자바를 무시하지 말라!!!!!

결론


위와 같은 문제들 때문에 구글은 ViewBinding, DataBinding 사용을 권장하고 있다.

참고

profile
😎

0개의 댓글