앱에서 리스트형 화면을 보여주기 위한 위젯 중 하나이다.
리스트를 위아래로 스크롤 할때 새로운 아이템을 생성하는 것이 아니라 스크롤해서 사라진 아이템이 새로운 아이템으로 대체되는 방식이다.
생성하는 아이템의 수가 한정되어 있기 때문에 자원관리가 용이하다.
RecyclerView.Adapter와 ViewHolder패턴을 사용하여 데이터와 뷰 바인딩을 관리한다.ListView에 비해 구현이 복잡하다.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
}
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
}
}
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))
}
}
X(트위터), 페이스북, 유튜브 등의 스크롤을 내릴 때 객체가 새로 생성된다고만 생각했지 이것을 재활용한다는 생각 자체는 해보지 못했는데 자원 관리 측면에서는 매우 유용한것같다.
스크롤을 반대 방향으로 할 때 서버에 다시요청이 가지 않도록 데이터 캐싱등을 활용하도록 구현하면 더 좋을 것 같다.