ViewModel을 학습한 내용을 이를 이전에 만들었던 FLO 어플에 적용하면서 이에 대해 제대로 학습하고, HiStory 어플에 적용하려고 한다. 그래서 이번에는 RecyclerView와 ViewModel에 대해 학습하여 이를 적용해보았다.
//HomeFragment.kt
val albumRecyclerViewAdapter = AlbumRVAdapter(homeViewModel.albumList)
binding.homeTodayRecyclerView.adapter = albumRecyclerViewAdapter
albumRecyclerViewAdapter.setMyItemClickListener(object : AlbumRVAdapter.MyItemClickListener{
override fun onItemClick(album: Album) {
changeAlbumFragment(album)
Log.d("home_Fragment", "change")
}
override fun onRemoveAlbum(position : Int) {
albumRecyclerViewAdapter.removeItem(position)
}
})
//AlbumRVAdapter.kt
class AlbumRVAdapter(private val albumList: ArrayList<Album>) : RecyclerView.Adapter<AlbumRVAdapter.ViewHolder>(){
// 클릭 인터페이스
interface MyItemClickListener {
fun onItemClick(album : Album)
fun onRemoveAlbum(position: Int)
}
// 리스너 객체를 전달받는 함수랑 리스너 객체를 저장할 변수
private lateinit var mItemClickListener: MyItemClickListener
fun setMyItemClickListener(itemClickListener: MyItemClickListener){
mItemClickListener = itemClickListener
}
// 뷰 홀더를 생성할 때 호출되는 함수 -> 아이템 뷰 객체를 만들어서 뷰 홀더에 넣어줌
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val binding: ItemAlbumBinding = ItemAlbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return ViewHolder(binding)
}
fun addItems(albums: ArrayList<Album>) {
albumList.clear()
albumList.addAll(albums)
notifyDataSetChanged()
}
fun addItem(album: Album){
albumList.add(album)
notifyDataSetChanged()
}
// notify 잊지말것!!
fun removeItems() {
albumList.clear()
notifyDataSetChanged()
}
fun removeItem(position: Int) {
albumList.removeAt(position)
notifyDataSetChanged()
}
// 생성된 뷰 홀더에 데이터를 바인딩해줘야 할 때마다 호출됨
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(albumList[position])
}
// 데이터 세트 크기를 알려주는 함수, 리사이클러뷰가 마지막이 언제인지를 알 수 있음
override fun getItemCount(): Int = albumList.size
// 뷰홀더 : 아이템 객체들을 재활용 하기 위한 그릇
inner class ViewHolder(val binding: ItemAlbumBinding) : RecyclerView.ViewHolder(binding.root){
init {
binding.itemAlbumImgIv.setOnClickListener {
mItemClickListener.onItemClick(albumList.get(adapterPosition))
Log.d("AlbumRVA", "click${albumList.get(adapterPosition)}")
}
}
fun bind(album : Album){
binding.itemTitleTv.text = album.title
binding.itemSingerTv.text = album.singer
// binding.itemAlbumImgIv.setImageResource(album.coverImg!!)
}
}
}
이전에는 onBindViewHolder에서 클릭리스너를 생성해주었는데, 이 때 생길 수 있는 문제가 리사이클러뷰의 내용이 바뀔 때마다 해당 함수가 호출되기 때문에 리스너가 새롭게 생성되고 그 결과 memory leak 문제가 생길 수 있기 때문에 이를 ViewHolder에서 해주었다.
리사이클러뷰를 사용할 View(HomeFragment)에서 인터페이스를 정의해주었다. 그러면 AlbumRVAdapter에서 이를 클릭 리스너로 설정하면 해당 아이템을 클릭했을 때, 해당 뷰홀더에서 onItemClick()이 호출되고, album을 넘겨주면 이 값을 가지고 Fragment 전환이 이루어진다.
코드는 깃허브 에서 확인하실 수 있습니다.
'Kotlin_study' 카테고리의 다른 글
[HiStory 리팩토링] LiveData에서 Flow로 전환 (0) | 2023.02.20 |
---|---|
[HiStory 리팩토링] 3. 카카오 로그인 기능 적용(2) (0) | 2023.01.04 |
[HiStory 리팩토링] 2. 카카오 로그인 기능 적용 (0) | 2023.01.03 |
[HiStory 리팩토링] 1. 리팩토링을 시작하다 (0) | 2022.12.28 |
[Kotlin] Custom Calendar Library(kizitonwose) 사용하기 (0) | 2022.07.13 |