RecyclerView를 사용하다면 비슷한 형태가 반복되는데 ,
반복되는 코드를 되게 싫어하는 편이라
Base형태로 만들어 상속받아 사용하는 편이다.
/**
* BaseViewHolder
* @param ITEM list의 들어가는 item type
* @param binding viewBinding
*/
abstract class BaseViewHolder<ITEM : Any>(
val binding: ViewBinding,
) : RecyclerView.ViewHolder(binding.root) {
abstract fun onBind(item: ITEM) // item Bind
}
먼저 BaseViewHolder이다, ITEM을 Generic으로 받으며,
연결할 뷰를 binding param으로 받는다.
그 뒤 holder에서 bind시켜줄 onBind함수를 구현해준다.
/**
* @param ITEM list의 들어가는 item type
* @param binding viewBinding
*/
abstract class BaseRecyclerAdapter<ITEM : Any, B : ViewBinding>(
) : RecyclerView.Adapter<BaseViewHolder<ITEM>>() {
open var itemList: MutableList<ITEM> = mutableListOf()// 아이템 리스트 ||기본 empty
abstract fun initViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<ITEM>
//아이템 insert
open fun insertItems(items: List<ITEM>?) {
this.itemList.run {
clear()
itemList.addAll(items ?: emptyList())
}
notifyDataSetChanged()
}
open fun addItem(getItem: ITEM) {
val index = itemList.size
itemList.add(getItem)
notifyItemInserted(index)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<ITEM> {
return initViewHolder(parent, viewType)
}
override fun getItemCount(): Int = itemList.size
override fun onBindViewHolder(holder: BaseViewHolder<ITEM>, position: Int) {
holder.onBind(itemList[position])
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
}
BaseRecylcerAdapter에서는 ITEM과 B를 제너릭으로 받는다.
그리고 initViewHolder함수 통해 onCreateViewHolder과 연결해준다.
abstract class BaseViewBindingRecyclerAdapter<ITEM : Any, B : ViewBinding>(
val inflate: (LayoutInflater, ViewGroup?, Boolean) -> B,
) : BaseRecyclerAdapter<ITEM, B>() {
abstract fun onBindItem(binding: B, item: ITEM) // 아이템 연결
override fun initViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<ITEM> {
val binding: B = inflate(LayoutInflater.from(parent.context), parent, false)
return object : BaseViewHolder<ITEM>(binding) {
override fun onBind(item: ITEM) {
this@BaseViewBindingRecyclerAdapter.onBindItem(binding, item)
}
}
}
}
abstract class BaseDataBindingRecyclerAdapter<ITEM : Any, B : ViewBinding>(
@LayoutRes private val resId: Int,
) : BaseRecyclerAdapter<ITEM, B>() {
abstract fun onBindItem(binding: B, item: ITEM) // 아이템 연결
override fun initViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<ITEM> {
val binding: B = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
resId,
parent,
false
)
return object : BaseViewHolder<ITEM>(binding) {
override fun onBind(item: ITEM) {
this@BaseDataBindingRecyclerAdapter.onBindItem(binding, item)
}
}
}
}
ViewBinding또는 Databinding형태로 바로 연결할수 있게 구현하였다.
기본적으로 viewHolder 을 생성하지 않고 자동으로 BaseViewHolder 을 기반으로 생성해준다
필요하다면, 상속받은 클래스에서 override시켜서 다시 만들어주자.
사용법 예시이다.
class RecipeRecentViewPager :
BaseDataBindingRecyclerAdapter<Recipe, ItemMainFoodBinding>(R.layout.item_main_food) {
override fun onBindItem(binding: ItemMainFoodBinding, item: Recipe) {
binding.recipe = item
}
}
현재 만들고 있는 앱에서 복사해왔다.