안드로이드 RecyclerView

김민준·2024년 3월 1일

RecyclerView란?
공부하며 느낀 점

RecyclerView란?

앱에서 리스트형 화면을 보여주기 위한 위젯 중 하나이다.

리스트를 위아래로 스크롤 할때 새로운 아이템을 생성하는 것이 아니라 스크롤해서 사라진 아이템이 새로운 아이템으로 대체되는 방식이다.

생성하는 아이템의 수가 한정되어 있기 때문에 자원관리가 용이하다.

장단점

장점

  1. 뷰 재활용 : 메모리 사용량을 줄이고 스크롤 성능을 향상, 최적화한다.
  2. 다양한 레이아웃을 지원한다.
  3. 애니메이션과 데코레이션 지원 : 기본 애니메이션 자동 제공 및 커스텀 애니메이션 추가
  4. 높은 확장성 : RecyclerView.AdapterViewHolder패턴을 사용하여 데이터와 뷰 바인딩을 관리한다.

단점

  1. 구현 복잡성 : ListView에 비해 구현이 복잡하다.
  2. 초기 학습 : 처음에 배워야할 것이 많다.
  3. 아이템 클릭 리스너를 제공하지 않는다.
  4. 표준화되지 않은 구현 : 코드 일관성 유지가 어렵다.

LayoutManager

RecyclerView 내부의 아이템들이 어떻게 배치될지를 결정하는 부분이다.

recyclerView.layoutManager = LinearLayoutManager(this) : 수직 리스트

recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) : 높이가 다른 수직리스트

recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) : 수평리스트

recyclerView.layoutManager = GridLayoutManager(this, n) : n열 그리드 리스트

커스텀 레이아웃 : RecyclerView.LayoutManager를 상송받아 커스텀을 할 수 있다. onLayoutChildren(Recycler recycler, State state)등의 메소드를 오버라이드한다.

Flexbox 레이아웃 적용 : 아이템 크기에 따라 자동 줄 바꿈처리, 정렬, 간격, 순서 등 다양한 스타일 옵션을 제공한다.


// build.gradle

dependencies {
    implementation 'com.google.android:flexbox:3.0.0' // Flexbox 라이브러리 버전은 변경될 수 있습니다.
}

// 액티비티 또는 프래그먼트

val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.layoutManager = FlexboxLayoutManager(this).apply {
    // 방향 설정
    flexDirection = FlexDirection.ROW
    // 내용 정렬 방식 설정
    justifyContent = JustifyContent.FLEX_START
}

ViewHolder

RecyleView의 개별 아이템을 담기 위한 객체


// 예시

inner class ItemViewHolder(binding: ItemLayoutBinding) :
        RecyclerView.ViewHolder(binding.root) {
        val timeView = binding.timeTv
        private val temperatureView = binding.tempTv
        private val weatherStatusView = binding.weatherIv
        private val rainStatusView = binding.rainIv
        fun bind(item: WeatherData?) {
            val res = timeView.context.resources
            timeView.text = item?.time?.toTimeFormat()
            temperatureView.text = res.getString(R.string.temp_text, item?.temperature)
            weatherStatusView.setImageResource(item?.skyStatus?.icon ?: R.drawable.ic_sunny)
            rainStatusView.setImageResource(item?.rainState?.icon ?: R.drawable.ic_sunny)
        }

        private fun String.toTimeFormat(): String {
            return if (this.length == 4) "${this.substring(0, 2)}:${this.substring(2)}" else this
        }
    }

RecyclerView.Adapter

  • 데이터와 뷰 홀더를 연결해준다.
  • 데이터 셋의 변경 사항을 리사클러 뷰에 알리고, 데이터를 기반으로 뷰를 생성한다.
class WeatherItemListAdapter :
    ListAdapter<WeatherData, WeatherItemListAdapter.ItemViewHolder>(object :
        DiffUtil.ItemCallback<WeatherData>() {
        override fun areItemsTheSame(oldItem: WeatherData, newItem: WeatherData): Boolean {
            return oldItem.time == newItem.time
        }

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

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = ItemLayoutBinding.inflate(inflater, parent, false)
        return ItemViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        holder.bind(getItem(position))
    }
}

공부하며 느낀 점

  1. X(트위터), 페이스북, 유튜브 등의 스크롤을 내릴 때 객체가 새로 생성된다고만 생각했지 이것을 재활용한다는 생각 자체는 해보지 못했는데 자원 관리 측면에서는 매우 유용한것같다.

  2. 스크롤을 반대 방향으로 할 때 서버에 다시요청이 가지 않도록 데이터 캐싱등을 활용하도록 구현하면 더 좋을 것 같다.

profile
node 개발자

0개의 댓글