안드로이드 RecyclerView Adapter View Binding 적용하기

activity는 전부 뷰 바인딩 적용해놓고 RecyclerView 부분은 초기에 파일을 복사+붙여넣기를 반복하다보니 전부 findViewById로 적용해 온 내 자신..(;´д`)ゞ

🙋🏻‍♀️ inflate란?
xml에 표기된 레이아웃들을 메모리에 객체화 시키는 것

💻 findViewById 를 적용한 코드

class ReviewPhotoAdapter(val callback: (String) -> Unit) :
    ListAdapter<String, ReviewPhotoAdapter.ViewHolder>(diffUtil) {

    inner class ViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        fun bind(item: String) {
            val reviewImageView = view.findViewById<ImageView>(R.id.reviewImageView)

            Glide.with(TestApp.instance)
                .load(item)
                .error(R.drawable.ic_person)
                .into(reviewImageView)

            reviewImageView.setOnClickListener {
                callback(item)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context)
                .inflate(R.layout.item_review_photo, parent, false)
        )
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        return holder.bind(currentList[position])
    }

    companion object {
        val diffUtil = object : DiffUtil.ItemCallback<String>() {
            override fun areItemsTheSame(oldItem: String, newItem: String): Boolean {
                return oldItem == newItem
            }

            override fun areContentsTheSame(oldItem: String, newItem: String): Boolean {
                return oldItem == newItem
            }
        }
    }
}

위에 가져온 코드는 간단한 코드라 복잡해 보이지 않지만 뷰가 엄청 많은 레이아웃을 연결하면 findViewById로 도배가 되겠지요 핫 😅 그래서 결국 RecyclerView 부분도 전부 뷰 바인딩 (View Binding)을 적용해주기로 결정했다.

💻 View Binding 을 적용한 코드

class ReviewPhotoAdapter(val callback: (String) -> Unit) :
    ListAdapter<String, ReviewPhotoAdapter.ViewHolder>(diffUtil) {

    inner class ViewHolder(private val binding: ItemReviewPhotoBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(item: String) {
            Glide.with(TestApp.instance)
                .load(item)
                .error(R.drawable.ic_person)
                .into(binding.reviewImageView)

            binding.reviewImageView.setOnClickListener {
                callback(item)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            // ItemReviewPhotoBinding 클래스로 만들어지는 binding 인스턴스를 사용하도록 변경
            ItemReviewPhotoBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        return holder.bind(currentList[position])
    }

    companion object {
        val diffUtil = object : DiffUtil.ItemCallback<String>() {
            override fun areItemsTheSame(oldItem: String, newItem: String): Boolean {
                return oldItem == newItem
            }

            override fun areContentsTheSame(oldItem: String, newItem: String): Boolean {
                return oldItem == newItem
            }
        }
    }
}

View Binding 을 쓰면 어떤 점이 좋을까 ?

코드가 간결화 되는 장점도 있지만 findViewById는 사람이 직접 작성해 연결을 하다보니 남발하다보면 실수를 할 수 있기 마련인데..! findViewById<ⓐ>(R.id.reviewImageView) ⬅ ⓐ 부분에 뷰를 잘못 연결하는 실수를 할 리도 없고 (ImageView를 넣어주어야 하는데 TextView를 입력하는 등), 간혹 안드로이드 4.1 이전 버전에서 Kotlin Extension 기능으로 findViewById 마저 생략하는 경우도 있는데 만약 다른 xml 파일과 id가 같을 경우 해당 뷰를 못 찾아 앱이 다운되어버리는 일도 발생한다. 결국 바인딩 된 xml 파일에서만 해당 id를 찾기 때문에 뷰 바인딩 (View Binding) 최고다 이거에용,,👍🏻

좋은 웹페이지 즐겨찾기