background
Kotlin4분

리사이클러 뷰

2025년 2월 20일

RecyclerView

RecyclerView는 안드로이드 앱에서 리스트 형태의 데이터를 표시하는데 사용되는 위젯.

여러 아이템을 스크롤 가능한 리스트로 표현하며, 많은 아이템을 효율적으로 관리하고 보여주는 역할을 함

  • Recycle
  • View를 재활용
  • ListView와의 차이점
    • LIstView
    • 스크롤 할 때마다 위에 있던 아이템 삭제, 맨 아래 아이템은 생성 이 과정을 반복
    • 아이템 개수 만큼 삭제, 생성 반복 성능에 좋지 않다
    • RecyclerView
    • 스크롤 할 때마다 위에 있던 아이템이 재활용 되며 아래로 이동하여 재사용 됨
    • ex) 10개 정도 View를 만들고 10개를 재활용하여 사용함
    • View를 계속해서 만드는 ListView의 단점 보완함

RecyclerView 기본 구조

  • Adapter
    • 데이터를 목록 형태로 보여주기 위해 사용됨
    • 데이터를 아이템 뷰와 연결하는 역할을 함
    • 데이터와 RecyclerView 사이의 통신을 위한 연결체
  • ViewHolder
    • 아이템 뷰를 저장하고 표시하는 역할을 함
    • 스크롤 해서 위로 올라간 View를 재활용하기 위해 View를 기억하는 역할을 함
  • LayoutManager
    • 데이터나 아이템들이 RecyclerView 내부에서 배치되는 형태를 관리함
      • LinearLayoutManager : 수평, 수직으로 배치 시켜줌
      • GridLayoutManager : 그리드 화면으로 배치 시켜줌
      • StaggeredGridLayoutManager : 높이가 불규칙한 그리드 화면으로 배치 시켜줌

LayourManager 정렬 방식

  • LinearLayoutManager : 수직(기본값)
kotlin
binding.recyclerView.layoutManager = LinearLayoutManager(this)
  • LinearLayoutManager : 수평
  • true : 순서 / false : 역순
kotlin
binding.recycleView.layoutManager = LinearLayourManger(this, LinearLayoutManager.HORIZONTAL, false)
  • GridLayoutManager : 수직(기본값)
kotlin
binding.recycelrView.layoutManager = GridLayoutManager(this,3)
  • GridLayoutManager : 수평
kotlin
binding.recycelrView.layoutManager = GridLayoutManager(this,3,GridLayoutManager.HORIZONTAL,false)
  • StaggeredGridLayoutManager
  • VERTICAL : 수직 / HORIZONTAL : 수평
  • 각 항목의 크기 별로 불규칙한 그리드 형식
kotlin
binding.recycelrView.layoutManager = StaggeredGridLayoutManager(3,LinearLayoutManager.VERTICAL)

View Binding

이름처럼, 레이아웃과 코틀린 파일을 묶어주는 방식임

기존의 findViewById를 대체 하며 상호 작용하는 코드를 쉽게 작성할 수 있음

예를 들어 `TextView` 를 업데이트 하는 경우
kotlin
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // findViewById로 View를 가져오기
        val textView: TextView = findViewById(R.id.textView)
        textView.text = "Hello, findViewById!"
    }
}

딱 봐도 코드가 길어보이고 관리하기 어려워 보인다…

다음 ViewBinding
kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.app.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ViewBinding 초기화
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // ViewBinding으로 View를 참조
        binding.textView.text = "Hello, ViewBinding!"
    }
}

코드가 간결해보이고 가독성이 좋다!

  • findViewById와의 차이점
    1. Null Safety

      바인딩 기능을 사용하면, 앱이 레이아웃의 각 뷰를 직접 참조할 수 있게 해주는 안전한 코드를 자동으로 생성함. 이는 뷰를 사용할 때 ‘null’값으로 인한 오류 즉, 아직 뷰가 렌더링 되지 않았는데 그 뷰를 사용하려고 할 때 생길 수 있는 문제를 예방 해줌

      ex) 레이아웃에 버튼이 있어야 하는데 아직 버튼이 생성되지 않았다면, 바인딩은 이를 안전하게 처리하여 앱이 크러쉬 되지 않게 해줌

      또, 만약 레이아웃의 일부만 뷰가 있다면, 뷰 바인딩은 해당 뷰가 ‘가능성 있는 null(Nullable)’임을 알려줘, 개발자가 더 주의 깊게 코드를 작성할 수 있도록 도와줌

    2. 타입 안정성(Type Safety)

      XML 레이아웃 파일에서 정의된 뷰의 타입과 자동 생성된 바인딩 클래스의 필드 타입이 항상 일치하기 때문에, 타입이 서로 맞지 않아 발생할 수 있는 오류를 방지해준다.

      ex) 이미지 뷰(ImageView)에 텍스트를 설정하려고 하면 오류가 발생하는데, 바인딩을 사용하면 이런 실수를 할 가능성이 없어짐

      즉, ImageView ⇒ ImageView, TextView ⇒ TextView 로만 사용되게끔 하며, 잘못된 타입 사용으로 인한 오류 발생 방

RecyclerView 사용

1. 의존성 추가: build.gradle 파일에 RecyclerView 의존성 주입

kotlin
implementation("androidx.recyclerview:recyclerview:1.3.1")

gradle 설정

xml
android{
	viewBindint{
		enabled = true
	}
	buildFeatures{
		viewBinding = true	
	}
}

2. 아이템 레이아웃 생성 : 아이템 하나의 레이아웃을 작성 함

xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="@android:color/black"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

3. Adapter 생성 : RecyclerView.Adapter 클래스를 상속한 Adapter클래스 생성

4. ViewHolder 생성 : RecyclerView.ViewHolder 클래스를 상속한 ViewHolder 클래스를 생성함

kotlin
package com.example.constraintlayout_practice.adapter

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.constraintlayout_practice.databinding.ItemBinding

// RecyclerView의 Adapter 클래스. String 리스트를 받아서 RecyclerView의 각 항목에 데이터를 표시함
class RecyclerViewAdapter(private val items: List<String>) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {

    // ViewHolder를 생성하는 메서드
    // 여기서 레이아웃 XML 파일을 바인딩하고 ViewHolder에 전달
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // item.xml 레이아웃을 바인딩
        val binding = ItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ViewHolder(binding) // ViewHolder를 반환
    }

    // 각 ViewHolder에 데이터를 바인딩하는 메서드
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(items[position]) // position에 해당하는 데이터를 ViewHolder에 바인딩
    }

    // RecyclerView의 전체 항목 수 반환
    override fun getItemCount(): Int = items.size

    // RecyclerView의 ViewHolder 클래스. 하나의 항목에 해당하는 View를 관리
    inner class ViewHolder(private val binding: ItemBinding) : RecyclerView.ViewHolder(binding.root) {

        // 데이터(item)를 View에 바인딩하는 메서드
        fun bind(item: String) {
            binding.textView.text = item // item 데이터를 TextView에 설정
        }
    }
}

5. LayoutManager 설정 : RecyclerView에 사용할 레이아웃 매니저를 설정함

kotlin
package com.example.constraintlayout_practice.ui

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.constraintlayout_practice.R
import com.example.constraintlayout_practice.adapter.RecyclerViewAdapter
import com.example.constraintlayout_practice.custom.CustomItemDecoration
import com.example.constraintlayout_practice.databinding.ActivityRecyclerviewBinding

class RecyclerViewActivity  : AppCompatActivity() {
    private lateinit var binding : ActivityRecyclerviewBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val items = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
        val adapter = RecyclerViewAdapter(items)
        val backButton = binding.goBack

        val dividerDecoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)

        val spaceInPixels = resources.getDimensionPixelSize(R.dimen.recycler_item_space)
        val spaceDecoration = CustomItemDecoration(spaceInPixels)


        binding.recyclerView.addItemDecoration(dividerDecoration)
        binding.recyclerView.addItemDecoration(spaceDecoration)
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter



        backButton.setOnClickListener() {
            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }

    }
}

결과

image.png

image.png

다음처럼, 밑으로 내리면 item들을 순회하면서 item을 보여줌

추가 아이템 간격 및, 구분선 추가 하기

  1. DivderItemDecoration 클래스를 사용, 수평선 추가
kotlin
val dividerDecoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
 
 binding.recyclerView.addItemDecoration(dividerDecoration)
  1. 커스텀으로 간격 설정 후 추가

    • 간격 설정
    xml
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <dimen name="recycler_item_space">16dp</dimen>
        <dimen name="recycler_margin">24dp</dimen>
    </resources>
    
    • ItemDecoration을 상속받는 커스텀 클래스 생성
    kotlin
    package com.example.constraintlayout_practice.custom
    
    import android.graphics.Rect
    import android.view.View
    import androidx.recyclerview.widget.RecyclerView
    
    class CustomItemDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
        override fun getItemOffsets(
            outRect: Rect,
            view: View,
            parent: RecyclerView,
            state: RecyclerView.State
        ) {
            super.getItemOffsets(outRect, view, parent, state)
            outRect.bottom = space
        }
    }
    
    • 레이아웃에 간격 설정
    xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.RecyclerViewActivity">
    
        <Button
            android:id="@+id/goBack"
            android:layout_width="300dp"
            android:layout_height="200dp"
            android:layout_margin="100dp"
            android:paddingStart="@dimen/recycler_margin"
            android:paddingEnd="@dimen/recycler_margin"
            android:clipToPadding="false"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:text="뒤로 가기"
            />
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/guideline3"
            app:layout_constraintVertical_bias="1.0"
            tools:listitem="@layout/item" />
    
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.2"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    • 액티비티에 속성 추가
    kotlin
    package com.example.constraintlayout_practice.ui
    
    import android.content.Intent
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.recyclerview.widget.DividerItemDecoration
    import androidx.recyclerview.widget.LinearLayoutManager
    import com.example.constraintlayout_practice.R
    import com.example.constraintlayout_practice.adapter.RecyclerViewAdapter
    import com.example.constraintlayout_practice.custom.CustomItemDecoration
    import com.example.constraintlayout_practice.databinding.ActivityRecyclerviewBinding
    
    class RecyclerViewActivity  : AppCompatActivity() {
        private lateinit var binding : ActivityRecyclerviewBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            val items = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
            val adapter = RecyclerViewAdapter(items)
            val backButton = binding.goBack
    
            val dividerDecoration = DividerItemDecoration(this, DividerItemDecoration.VERTICAL)
    
            val spaceInPixels = resources.getDimensionPixelSize(R.dimen.recycler_item_space)
            val spaceDecoration = CustomItemDecoration(spaceInPixels)
    
    
            binding.recyclerView.addItemDecoration(dividerDecoration)
            binding.recyclerView.addItemDecoration(spaceDecoration)
            binding.recyclerView.layoutManager = LinearLayoutManager(this)
            binding.recyclerView.adapter = adapter
    
    
    
            backButton.setOnClickListener() {
                val intent = Intent(this, SecondActivity::class.java)
                startActivity(intent)
            }
    
        }
    }
    

결과

image.png

image.png

클릭 시 이벤트 처리

대체로 RecyclerView에서 아이템을 클릭할 때 이벤트를 처리하는 방법은 ViewHolder에서 클릭 리스너를 설정하는 방식으로 처리하는 경우가 많음

단계

  1. ViewHolder에서 클릭 리스너 설정: 각 아이템을 클릭했을 때 발생할 이벤트를 처리 할 수 있도록 ViewHolder 내에서 클릭 리스너를 설정함
kotlin
private val onItemClick: (String) -> Unit

inner class ViewHolder(private val binding: ItemBinding) : RecyclerView.ViewHolder(binding.root) {
        // 아이템 클릭 이벤트 리스너 설정
        init {
            itemView.setOnClickListener {
                val clickedItem = items[bindingAdapterPosition]
                onItemClick(clickedItem)
            }
        }
  1. RecyclerViewActivity에서 아이템 클릭 시 클릭한 아이템 RecyclerView로 만들기
kotlin
// 추가된 아이템을 담을 리스트 생성
	    private val addedItems = mutableListOf<String>()
    
  // RecyclerView 어댑터 생성, 아이템 클릭 시 addedItems 리스트에 아이템 추가
      val adapter = RecyclerViewAdapter(items) { item ->
          addedItems.add(item) // 클릭된 아이템 추가
          Toast.makeText(this, "$item added", Toast.LENGTH_SHORT).show()

          // addedItemsRecyclerView 업데이트
          updateAddedItemsRecyclerView()
      }
  // 추가된 아이템을 표시할 두 번째 RecyclerView 설정
  binding.addedItemsRecyclerView.layoutManager = LinearLayoutManager(this)
        val addedItemsAdapter = RecyclerViewAdapter(addedItems) { addedItem ->
            // 추가된 아이템 클릭 시 토스트 메시지 표시
            Toast.makeText(this, "$addedItem Clicked", Toast.LENGTH_SHORT).show()
        }
        binding.addedItemsRecyclerView.adapter = addedItemsAdapter
   
   // addedItemsRecyclerView 업데이트 함수
    private fun updateAddedItemsRecyclerView() {
        // 두 번째 RecyclerView 어댑터에 데이터 변경을 반영
        val addedItemsAdapter = binding.addedItemsRecyclerView.adapter as RecyclerViewAdapter
        addedItemsAdapter.notifyDataSetChanged()
    }

심화 (Youtube api 활용 동영상 재생 기능 (1/4))

Muti-View 타입 활용해서 썸네일, 영상 제목, 생성 일자, 서브 타이틀 가져오기

  1. RecyclerView 아이템 레이아웃 파일

    다양한 데이터를 한 화면에서 보여주기 위해서 Multi-View 방식 사용, 이를 위해 각 아이템의 레이아웃 정의 함

    Activitiy 파일

    xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ui.RecyclerViewActivity">
    
        <!-- 뒤로 가기 버튼 -->
        <Button
            android:id="@+id/goBack"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="뒤로 가기"
            android:layout_marginTop="16dp"
            android:layout_marginStart="16dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
        <!-- 첫 번째 RecyclerView (영상 리스트) -->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="0dp"
            android:layout_height="300dp"
            app:layout_constraintTop_toBottomOf="@id/goBack"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />
    
        <!-- 가이드라인 -->
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.2"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    item 파일

    xml
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/thumbnail"
            android:layout_width="100dp"
            android:layout_height="70dp"
            android:layout_margin="10dp"
            android:src="@drawable/combined_image"
            android:contentDescription="Thumbnail"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Video Title"
            android:textSize="16sp"
            android:layout_marginTop="10dp"
            app:layout_constraintStart_toEndOf="@+id/thumbnail"
            app:layout_constraintTop_toTopOf="parent"/>
        <TextView
            android:id="@+id/subtitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Subtitle"
            android:textSize="14sp"
            app:layout_constraintStart_toStartOf="@+id/title"
            app:layout_constraintTop_toBottomOf="@+id/title" />
    
        <TextView
            android:id="@+id/date"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="2025-01-19"
            android:textSize="12sp"
            android:layout_marginTop="5dp"
            app:layout_constraintStart_toStartOf="@id/title"
            app:layout_constraintTop_toBottomOf="@id/subtitle" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. RecyclerViewAdapter 설정(더미 데이터, Multi-view 활용)

    kotlin
    package com.example.constraintlayout_practice.adapter
    
    import android.view.LayoutInflater
    import android.view.ViewGroup
    import androidx.recyclerview.widget.RecyclerView
    import com.example.constraintlayout_practice.data.VideoItem
    import com.example.constraintlayout_practice.databinding.ItemVideoBinding
    
    //
    
    class VideoAdapter(private val videoList: List<VideoItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val binding = ItemVideoBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            return VideoViewHolder(binding)
        }
    
        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            val videoItem = videoList[position]
            (holder as VideoViewHolder).bind(videoItem)
        }
    
        override fun getItemCount(): Int = videoList.size
    
        inner class VideoViewHolder(private val binding: ItemVideoBinding) : RecyclerView.ViewHolder(binding.root) {
            fun bind(item: VideoItem) {
                binding.title.text = item.title
                binding.subtitle.text = item.subtitle
                binding.date.text = item.date
                // 썸네일을 리소스 이미지로 설정
                binding.thumbnail.setImageResource(item.thumbnailRes)
            }
        }
    }
    
  3. 모델 생성

    kotlin
    package com.example.constraintlayout_practice.data
    
    data class VideoItem (
        val title : String,
        val subtitle : String,
        val date : String,
        val thumbnailRes: Int,
    //    val thumbnail : String,
    //    val videoUrl : String
    )
    
  4. Activity 및, LayoutManager 코드 작성

    kotlin
    class RecyclerViewActivity : AppCompatActivity() {
        private lateinit var binding : ActivityRecyclerviewBinding
        private val videoList = mutableListOf<VideoItem>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            videoList.add(VideoItem("Video 1", "Subtitle 1", "2025-01-19", R.drawable.combined_image))
            videoList.add(VideoItem("Video 2", "Subtitle 2", "2025-01-19", R.drawable.combined_image))
            videoList.add(VideoItem("Video 3", "Subtitle 3", "2025-01-19", R.drawable.combined_image))
            videoList.add(VideoItem("Video 3", "Subtitle 3", "2025-01-19", R.drawable.combined_image))
    
            val adapter = VideoAdapter(videoList)
    
    //        val adapter = VideoAdapter(videoList) { videoItem ->
    //            // 썸네일 클릭 시 해당 영상 URL로 이동
    //            val fragment = VideoFragment.newInstance(videoItem.videoUrl)
    //            supportFragmentManager.beginTransaction()
    //                .replace(R.id.fragmentContainer, fragment)
    //                .addToBackStack(null)
    //                .commit()
    //        }
            val spaceInPixels = resources.getDimensionPixelSize(R.dimen.recycler_item_space)
            val spaceDecoration = CustomItemDecoration(spaceInPixels)
    
    
            binding.recyclerView.layoutManager = LinearLayoutManager(this)
            binding.recyclerView.adapter = adapter
            binding.recyclerView.addItemDecoration(spaceDecoration)
    
        }
    }
    

결과

image.png

image.png

image.png

image.png

image.png

image.png

Recycle View로 썸네일, 타이틀, 생성일을 받아올 수 있게 됐다

이제 Recycle View로 뼈대 만들었으니, Fragment 학습 후 실제 데이터 연동 해봐야 겠다

끗!

태그

#Kotlin#AndroidStudio