Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

yourginieus

Recyclerview 기초 본문

Android/Android Kotlin 기초 실습 정리

Recyclerview 기초

EOJIN 2022. 12. 13. 21:57
  • 안드로이드에서 가장 일반적인 UI 작업 : 데이터 목록/그리드 표시
    • 이러한 기능을 위해 Recyclerview 존재
  • 장점
    • 대규모 리스트에 매우 효율적임
    • 기본적으로 Recyclerview는 현재 화면에 표시되는 항목을 처리하거나 그리는 데만 작동함
      • 목록에 1000개가 있어도 화면에 10개 요소만 표시된다면 Recyclerview는 화면에 10개의 아이템을 그릴 수 있을 정도로만 동작함
      • 사용자가 스크롤하면 Recyclerview는 화면에 표시되는 새로운 아이템을 파악하고 그 아이템을 표시하기에 충분한 작업만 수행함
    • item이 화면에서 스크롤되어 나가면 그 아이템의 view는 재활용됨(recycled)
      • 아이템이 새로운 콘텐츠로 채워진다는 것을 의미
      • -> 처리 시간을 절약하고 목록이 부드럽게 스크롤되게 함
    • 아이템이 변경될 경우, 전체를 다시 그리는 대신 그 한 개의 항목만을 업데이트할 수 있음

The adapter pattern

  • 다른 나라에서 해당 국가의 콘센트를 사용하기 위해 어댑터를 사용하듯이, 인터페이스를 다른 인터페이스로 변환할 수 있음
    • software engineering의 adapter pattern도 이와 비슷함
    • 한 클래스의 API를 다른 API로 사용할 수 있음
  • Recyclerview는 app data를 리사이클러뷰가 표시할 수 있도록 adapter를 사용하여 변환함
  • app이 data를 저장하고 처리하는 방식을 변경하지 않고도 리사이클러뷰에 표시할 수 있도록!
  • sleep-tracker 앱에서는 데이터를 Room database에서 ViewModel을 변경하지 않고 Recyclerview가 표시하도록 adapter를 사용함

RecyclerView 구현

  • Data to display
  • RecyclerView instance : layout 파일에서 정의됨, view의 container 역할을 하기 위함
  • A layout for one item of data : 모든 list item이 동일할 경우, 모든 항목에 동일한 레이아웃을 사용할 수 있지만 필수는 아님. 아이템 레이아웃은 별도의 fragment layout으로 생성되어 한 번에 하나의 아이템 뷰를 생성하여 데이터로 채울 수 있음
  • A layout manager : layout manager는 view에서 UI components의 구성(레이아웃)을 다룸
  • A view holder : view holder는 ViewHolder 클래스를 상속받음. 이는 item layout에서 하나의 항목을 표시하기 위한 view 정보가 포함되어 있음
  • An adapter : 어댑터는 your data를 Recyclerview에 연결함. 이는 ViewHolder에서 data가 표시될 수 있도록 함. Recyclerview는 어댑터를 사용하여 화면에 데이터를 표시하는 방법을 알아냄

 

  • 리사이클러뷰에 어댑터 추가
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

아이템뷰&어댑터 만들기

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:textSize="24sp"
    android:paddingStart="16dp"
    android:paddingEnd="16dp"
    android:layout_width="match_parent"       
    android:layout_height="wrap_content" />
//Util.kt에 마지막에 아래 추가
//닫힘 괄호 다음에!
이 뷰 홀더는 예시고 나중에 교체할 거임
class TextItemViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView)

Sleep Night Adapter 작성

class SleepNightAdapter: RecyclerView.Adapter<TextItemViewHolder>() {}
//SleepNightAdapter의 맨 위에 list 생성
var data =  listOf<SleepNight>()
override fun getItemCount() = data.size
override fun onBindViewHolder(holder: TextItemViewHolder, position: Int) {
	holder.textView.text = item.sleepQuality.toString()
    
    holder.textView.text = item.sleepQuality.toString()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextItemViewHolder {
	val layoutInflater = LayoutInflater.from(parent.context)
    val view = layoutInflater
       .inflate(R.layout.text_item_view, parent, false) as TextView
       
    return TextItemViewHolder(view)
}
//이렇게 수정
var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

Recyclerview와 adapter 연결

val adapter = SleepNightAdapter()

binding.sleepList.adapter = adapter

어댑터에 데이터 가져오기

val nights = database.getAllNights()
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.data = it
   }
})

VeiwHolder를 inner class로 만들기

- SleepNightAdapter.kt의 innerclass 만들기

class SleepNightAdapter: RecyclerView.Adapter<SleepNightAdapter.ViewHolder>() {

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val sleepLength: TextView = itemView.findViewById(R.id.sleep_length)
val quality: TextView = itemView.findViewById(R.id.quality_string)
val qualityImage: ImageView = itemView.findViewById(R.id.quality_image)
}
    override fun onCreateViewHolder(
            parent: ViewGroup, viewType: Int): ViewHolder {
        val layoutInflater = 
            LayoutInflater.from(parent.context)
        val view = layoutInflater
                .inflate(R.layout.list_item_sleep_night, 
                         parent, false)
        return ViewHolder(view)
    }
   override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = data[position]
        val res = holder.itemView.context.resources
        holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
        holder.quality.text= convertNumericQualityToString(item.sleepQuality, res)
        holder.qualityImage.setImageResource(when (item.sleepQuality) {
            0 -> R.drawable.ic_sleep_0
            1 -> R.drawable.ic_sleep_1
            2 -> R.drawable.ic_sleep_2
            3 -> R.drawable.ic_sleep_3
            4 -> R.drawable.ic_sleep_4
            5 -> R.drawable.ic_sleep_5
            else -> R.drawable.ic_sleep_active
        })
    }
Comments