Fragment에서 반복되는 부분을 제거하기 위해 Base Fragment를 많이 만들어서 사용한다.
RecyclerView에서도 마찬가지로 반복되는 부분이 많은데, Base RecyclerView를 만들어서 이를 제거해보자.
abstract class BaseRecyclerViewAdapter<T : Any, VB : ViewBinding>(
private val bindingInflater: (inflater: LayoutInflater, parent: ViewGroup, attachToParent: Boolean) -> VB) : RecyclerView.Adapter<BaseRecyclerViewAdapter.BaseViewHolder<VB>>() {
var items = listOf<T>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<VB> {
val inflater = LayoutInflater.from(parent.context)
val binding = bindingInflater.invoke(inflater, parent, false)
return BaseViewHolder(binding)
}
var listener: ((view: View, item: T, position: Int) -> Unit)? = null
override fun getItemCount(): Int = items.size
abstract fun onBind(binding: VB, item: T)
class BaseViewHolder<VB : ViewBinding>(val binding: VB) : RecyclerView.ViewHolder(binding.root)
} // End of BaseRecyclerViewAdapter class
class MeetingSelectedCommitteeListAdapter() : BaseRecyclerViewAdapter<SimpleUser, ItemSimpleuserListBinding>(
{ inflater, parent, attachToParent ->
ItemSimpleuserListBinding.inflate(
inflater,
parent,
attachToParent
)
}
) {
override fun onBindViewHolder(
holder: BaseViewHolder<ItemSimpleuserListBinding>,
position: Int
) {
val item = items[position]
onBind(holder.binding, item)
} // End of onBindViewHolder()
override fun onBind(binding: ItemSimpleuserListBinding, item: SimpleUser) {
binding.tvSimpleuserListEmpId.text = item.empId.toString()
binding.tvSimpleuserListName.text = item.name
binding.ivSimpleUserCheck.visibility = View.GONE
} // End of onBind()
} // End of MeetingSelectedCommitteeListAdapter class
...
// Committeee RecyclerView
private lateinit var commitRecyclerView: RecyclerView
private lateinit var commitAdapter: MeetingSelectedCommitteeListAdapter
...
중간 부분 생략
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
commitListAdapter()
} // End of onViewCreated()
...
중간 부분 생략
...
private fun commitListAdapter() {
commitRecyclerView = binding.rvMeetingAddCommittee
commitAdapter = MeetingSelectedCommitteeListAdapter()
commitRecyclerView.layoutManager = LinearLayoutManager(mContext)
commitRecyclerView.adapter = commitAdapter
} // End of commitListAdapter()
...
BaseRecyclerView를 응용해서 검색기능을 만들어 보자
검색 기능을 만들어서 이름으로 검색해서 나오는 사람의 명단 RecyclerView에 표시할 것이다.
검색은 버튼을 따로만들지 않고 addTextChangedListener
를 EditText의 글자가 변경될 때 이벤트가 발생하도록 했다.
private fun initAdapter() {
recyclerView = binding.rvMeetingAddCommitteeList
meetingCommitteeListAdapter = MeetingCommitteeListAdapter(mContext)
recyclerView.layoutManager = LinearLayoutManager(mContext)
recyclerView.adapter = meetingCommitteeListAdapter
binding.edCommitteeAddCommitteeList.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable?) {
filterList(p0.toString())
}
})
} // End of initAdapter
private fun filterList(query: String?) {
val filteredCourseAry: ArrayList<SimpleUser> = ArrayList()
for (eachCourse in commiteeList) {
if (eachCourse.name.toLowerCase(Locale.ROOT)
.contains(query!!.toLowerCase(Locale.ROOT))
) {
filteredCourseAry.add(eachCourse)
}
}
meetingCommitteeListAdapter.setFilteredList(filteredCourseAry)
} // End of filterList()
class MeetingCommitteeListAdapter(private val context: Context) :
BaseRecyclerViewAdapter<SimpleUser, ItemSimpleuserListBinding>({ inflater, parent, attachToParent ->
ItemSimpleuserListBinding.inflate(
inflater, parent, attachToParent
)
}) {
override fun onBindViewHolder(
holder: BaseViewHolder<ItemSimpleuserListBinding>, position: Int
) {
val item = items[position]
onBind(holder.binding, item)
holder.binding.apply {
clSimpleuserListContainer.setOnClickListener {
item.isSelected = !item.isSelected
notifyItemChanged(position) // 변경된 아이템을 업데이트
}
}
} // End of onBindViewHolder()
override fun onBind(binding: ItemSimpleuserListBinding, item: SimpleUser) {
binding.apply {
tvSimpleuserListEmpId.text = item.empId.toString()
tvSimpleuserListName.text = item.name
if (!item.isSelected) {
ivSimpleUserCheck.background.setTint(
ContextCompat.getColor(
context, R.color.dark_gray
)
)
} else {
ivSimpleUserCheck.background.setTint(
ContextCompat.getColor(context, R.color.check_blue)
)
}
}
} // End of onBind()
fun setFilteredList(userList: List<SimpleUser>) {
this.items = userList
notifyDataSetChanged()
} // End of setFilteredList()
} // End of MeetingCommitteeListAdapter class
filterList()
함수를 통해서 검색되는 값만 필터링하여 RecyclerView의 List를 갱신한다.
여기서 this.items = userList
에서 this.items
가
이 부분이 된다.