I am using diff util to improve performance in my recyclerview as opposed to calling notifyDataSetChanged(). The recyclerview has a header with some chips which can reorder the list by aplhabetical order, highester score etc
When I click the chip in the header and the list reorders its effecting my position. For example if I have the ordered by hightest score and score 100% is position 1 (after the header) and I click the chip to reorder in reverse. Score 100% will now be at the bottom of the list and 0% will be at the top. But now I have to scroll all the way back to the top to see the header chips again. I want the list to reorder but I dont want my on screen position to change.
Here is my adapter code:
class DigitalTestsResultsAdapter(
private val interaction: Interaction? = null,
private val dateUtil: DateUtil,
private val theme: ThemeModel?,
private val username: String?
) : ListAdapter<ResultResponseModel, RecyclerView.ViewHolder>(ResultsDiffCallBack()) {
private val itemViewTypeHeader: Int = 0
private val itemViewTypeItem: Int = 1
private var filteredList = emptyList<ResultResponseModel>()
private val adapterScope = CoroutineScope(Dispatchers.Default)
class ResultsDiffCallBack : DiffUtil.ItemCallback<ResultResponseModel>() {
    override fun areItemsTheSame(
        oldItem: ResultResponseModel,
        newItem: ResultResponseModel
    ): Boolean {
        return oldItem.certificateUrl == newItem.certificateUrl
    }
    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(
        oldItem: ResultResponseModel,
        newItem: ResultResponseModel
    ): Boolean {
        return oldItem == newItem
    }
}
fun filterList(list: List<ResultResponseModel>, type: String) {
    adapterScope.launch {
        when (type) {
            "courseName" -> {
                filteredList = list.sortedBy { it.courseName }
            }
            "isCpd" -> {
                filteredList = list.sortedBy { it.courseName }.sortedByDescending { it.isCPD }
            }
            "organisationName" -> {
                filteredList = list.sortedBy { it.organisationName }
            }
            "roleName" -> {
                filteredList = list.sortedBy { it.roleName }
            }
            "score" -> {
                filteredList = list.sortedByDescending { it.score }
            }
            "submitTime" -> {
                filteredList = list.sortedByDescending { it.submitTime }
            }
        }
        withContext(Dispatchers.Main) {
            submitList(filteredList)
        }
    }
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when (viewType) {
        itemViewTypeHeader -> {
            DigitalTestsResultsHeaderViewHolder(
                RvDigitalTestResultsHeaderBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                )
            )
        }
        itemViewTypeItem -> {
            DigitalTestsResultsViewHolder(
                RvDigitalTestsResultsBinding.inflate(
                    LayoutInflater.from(parent.context),
                    parent,
                    false
                ),
                interaction = interaction
            )
        }
        else -> throw ClassCastException("Unknown viewType $viewType")
    }
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is DigitalTestsResultsHeaderViewHolder -> {
            holder.bind()
        }
        is DigitalTestsResultsViewHolder -> {
            holder.bind(currentList[position])
        }
    }
}
override fun getItemViewType(position: Int): Int {
    return if (position == 0) {
        itemViewTypeHeader
    } else {
        itemViewTypeItem
    }
}
override fun getItemCount(): Int {
    return if (!currentList.isNullOrEmpty()) {
        currentList.size
    } else 0
}
inner class DigitalTestsResultsHeaderViewHolder
constructor(
    private val binding: RvDigitalTestResultsHeaderBinding
) : RecyclerView.ViewHolder(binding.root) {
    fun bind() {
        with(binding) {
            with(theme) {
                userName.text = itemView.context.getString(R.string.hi_username, username)
                userName.setTextColourHex(this?.textModel?.primaryColor)
                chipCv.setCardBackgroundColourHex(this?.interfaceModel?.secondaryColor)
                testsChipGroup.setOnCheckedChangeListener { _, checkedId ->
                    when (checkedId) {
                        R.id.chipCertified -> {
                            chipCertified.isChecked = true
                            filterList(currentList, "isCpd")
                        }
                        R.id.chipCourse -> {
                            chipCourse.isChecked = true
                            filterList(currentList, "courseName")
                        }
                        R.id.chipHighestScore -> {
                            chipHighestScore.isChecked = true
                            filterList(currentList, "score")
                        }
                        R.id.chipRecent -> {
                            chipRecent.isChecked = true
                            filterList(currentList, "submitTime")
                        }
                        R.id.chipRole -> {
                            chipRole.isChecked = true
                            filterList(currentList, "roleName")
                        }
                        R.id.chipSchoolName -> {
                            chipSchoolName.isChecked = true
                            filterList(currentList, "organisationName")
                        }
                        else -> {
                        }
                    }
                }
            }
        }
    }
}
inner class DigitalTestsResultsViewHolder
constructor(
    private val binding: RvDigitalTestsResultsBinding,
    private val interaction: Interaction?
) : RecyclerView.ViewHolder(binding.root) {
    @SuppressLint("SetTextI18n")
    fun bind(item: ResultResponseModel?) {
        with(binding) {
            with(theme) {
                viewCertificateBtn.setOnClickListener {
                    interaction?.onItemSelected("certificateBtn", absoluteAdapterPosition, item)
                }
                retakeTestBtn.setOnClickListener {
                    interaction?.onItemSelected("retakeTestBtn", absoluteAdapterPosition, item)
                }
                resultsProgressBar.progress = item?.score?.toFloat() ?: 0f
                if (isValidHex(item?.roleColour)) {
                    resultsProgressBar.circleProgressColor = Color.parseColor(item?.roleColour)
                    resultsProgressBar.pointerColor = Color.parseColor(item?.roleColour)
                }
                score.text = item?.score.toString() + "%"
                title.text = item?.courseName
                date.text = dateUtil.formatStringDateToDDMMYYYY(item?.submitTime)
                role.text = item?.roleName
                schoolName.text = item?.organisationName
                title.setTextColourHex(this?.textModel?.primaryColor)
                retakeTestBtn.setTextColourHex(this?.textModel?.primaryColor)
                mainCv.setCardBackgroundColourHex(this?.interfaceModel?.secondaryColor)
                roleCv.setCardBackgroundColourHex(item?.roleColour)
                // Check if course is CPD and display CPD icon
                if (item?.isCPD == true) cpdLogo.visibility =
                    View.VISIBLE else cpdLogo.visibility = View.INVISIBLE
            }
        }
    }
}
interface Interaction {
    fun onItemSelected(
        tag: String,
        position: Int,
        result: ResultResponseModel?
    )
}
}

 
     
    