[Android] RecyclerView의 중복되는 부분을 제거해보자. BaseRecyclerViewAdapter 만들기

: ) YOUNG·2024년 4월 9일
1

안드로이드

목록 보기
17/30
post-thumbnail
post-custom-banner

Fragment에서 반복되는 부분을 제거하기 위해 Base Fragment를 많이 만들어서 사용한다.

RecyclerView에서도 마찬가지로 반복되는 부분이 많은데, Base RecyclerView를 만들어서 이를 제거해보자.






전체 예시 코드


BaseRecyclerViewAdapter.kt


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



Adapter 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


Fragment


...

	// 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

이 부분이 된다.

post-custom-banner

0개의 댓글