본문 바로가기

Kotlin/안드로이드 공부

RecyclerView 뽀개기

728x90

RecyclerView에 내가 하려던 것:

1. Databinding

2. DiffUtils

3. 다중선택 (RecyclerView Selection)

 

세 가지를 한 번에 하려다 보니까 모두 적용한 예시는 절대 없을 뿐더러 어디서 오류가 나는지 찾기가 힘들었다. ㅠㅠ 

 

Databinding

 

DiffUtils

NotifyDataChanged() 처럼 전체 데이터를 바꿔줄 경우 flicker 현상이 일어날 수 있다. DiffUtils의 존재를 알게 되었고 당장 적용해보고 싶었다. 하지만 검색을 하면 할수록 새로운 개념들이 나온다. NotifyDataChanged() 도 좋은 개념인 줄 알았는데 전혀 아니었다.

 

1. DiffUtils (Callback)

2. AsyncListDiffer (itemCallback)

3. ListAdapter

 

처음에는 Callback과 itemCallback? 도대체 이름말고 다른게 뭐지했는데 내가 이해한 바로는 AsyncListDiffer이 자체 멀티 쓰레드를 지원하며 DiffUtils은 인덱싱을 제공해준다.

 

밑의 코드는 AsyncListDiffer를 이용한 코드로, 두 함수만 override해주면 된다. 위의 함수에서 id등을 비교해주고 같을 경우 밑의 함수까지 실행되어 데이터 변경을 감지한다고 한다. equals()와 hashcode() 개념에 대해서도 다시 복습했는데, 코틀린에서는 data class를 사용하기 때문에 자동으로 두 함수를 정의해주고 있어 == 으로 비교해도 된다고 한다. 물론 id값처럼 고유의 값을 넣어주는 것이 정석!

object MyDiffCallback : DiffUtil.ItemCallback<Folder>() {
    override fun areItemsTheSame(
        oldItem: Folder,
        newItem: Folder
    ): Boolean {
        return oldItem == newItem
    }

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

}

하지만 ListAdapter는 AsyncListDiffer의 Wrapper class로 더 편리하게 사용할 수 있다. 

(처음엔 왜 RecyclerView를 검색했는데 List가 나오지..했는데 ListView와는 전혀 상관없는 단어였다.)

class GalleryAdapter : ListAdapter<Folder, GalleryAdapter.GalleryViewHolder>(MyDiffCallback) {

DiffUtilCallback을 만들고 ViewHolder를 정의해주고,

onBindViewHolder와 onCreateViewHolder만 override해주면 리사이클러뷰가 완성된다!

 

 

다중선택 (RecyclerView Selection)

일단 결론부터 말하자면 다중선택은 기능을 구현 완료했지만 정말 알 수 없는 IllegalArgumentException로 일단 기능을 삭제했다. 어떤 경우에 오류가 발생하는지 보기 위해 계속 동작시켜보았지만 검색해보니 대부분이 이유를 알 수 없는 오류로 인해 사용을 추천하지 않는다는 내용이 많았다. 다른 방법으로 구현하는 것이 훨씬 나을 듯 하다. 

 

다중 선택을 하려던 이유: 선택 사진 복수 삭제, 전체가 아닌 선택한 사진으로만 gif파일 만들기

현재 애니메이션까지는 만들었지만 이것을 파일로 내보내는 과정이 생각대로 되지 않아 일단 이 기능을 제외하고 출시해도 될 것 같다고 판단했다. 다중선택+GIF 기능은 나중에 업데이트하는 것으로 하고, 애니메이션 보기 기능만 안정적으로 완료하자.

 

 

더보기

(현재 코드는..)

package com.example.photochangerecord

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.example.photochangerecord.databinding.ItemGalleryBinding
import com.example.photochangerecord.viewmodel.Folder
import com.example.photochangerecord.viewmodel.Photo
import java.io.File

class GalleryAdapter : ListAdapter<Folder, GalleryAdapter.GalleryViewHolder>(MyDiffCallback) {

    var folder: Folder? = null
    var itemClick: ItemClick? = null

    interface ItemClick {
        fun onClick(view: View, position: Int, folder: Folder)
    }

    override fun getItemCount(): Int {
        return folder!!.photos.size
    }


    override fun onBindViewHolder(holder: GalleryViewHolder, position: Int) {
        if (itemClick != null) {
            holder?.itemView?.setOnClickListener { v ->
                itemClick?.onClick(v, position, folder!!)
            }
        }

        val photo = folder!!.photos[position]

        holder.bind(photo)
    }

    inner class GalleryViewHolder(private val binding: ItemGalleryBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(photo: Photo) {
            binding.galleryImageTitle.text =
                photo.absolute_file_path.substringAfterLast("/").substringBeforeLast(".jpg")
            binding.galleryImageView.load(File(photo.absolute_file_path)) {
                crossfade(true)
                crossfade(200)
                placeholder(R.drawable.loading)
            }
        }


    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GalleryViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val binding: ItemGalleryBinding =
            DataBindingUtil.inflate(layoutInflater, R.layout.item_gallery, parent, false)
        return GalleryViewHolder(binding)
    }

}





 

 

 

 

 

zion830.tistory.com/86

 

[Android] ListAdapter로 RecyclerView 효율적으로 사용하기 (DiffUtil, AsyncListDiffer)

안드로이드에서 동일한 레이아웃을 반복적으로 뿌려주는 리스트형 UI를 만들기 위해 RecyclerView가 사용된다. RecyclerView를 사용하려면 Adapter, LayoutManager, ViewHolder 이렇게 세가지 준비물이 필요하다.

zion830.tistory.com

 

gamjatwigim.tistory.com/120

 

RecyclerView 더 잘쓰기

0. 서론  RecyclerView는 안드로이드 개발자라면, 질리도록 볼것이고, 계속해서 사용할 것이다. 그래서 대부분의 기능에서 RecyclerView를 요구하고 있고, 이를 커스텀해서 사용하는 경우가 많다. 그래

gamjatwigim.tistory.com

 

'Kotlin > 안드로이드 공부' 카테고리의 다른 글

RecyclerView 안에 EditText  (0) 2021.07.05
Native Development Kit (NDK)  (0) 2021.02.26
kotlin enum  (0) 2021.01.05
Koin 의존성 주입  (0) 2021.01.05
ViewBinding vs DataBinding  (0) 2021.01.04