在recyclerview中管理多个计时器/处理程序



我有一个回收器视图,其中列出了不同的作业,每个作业都有一个进度条,因为你可以一次做多个作业。我目前正在使用一个处理程序来减少进度条,但它一次只适用于一个作业。我希望它被绑定到一个位置,而不是完整的回收器视图,这样我就可以一次运行多个处理程序。我如何更新我的适配器,使处理程序(或者另一个计时器,如果它能更好地工作的话(特定于[位置],而不是完整的回收器视图?

class JobAdapter(
private val context: Context,
private val dataset: List<JobList>
) : RecyclerView.Adapter<JobAdapter.ItemViewHolder>() {
class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view){
val tvJobName = view.findViewById<TextView>(R.id.tvJobName)
val tvJobTime = view.findViewById<TextView>(R.id.tvJobTime)
val tvJobReward = view.findViewById<TextView>(R.id.tvJobReward)
val pbJobTime = view.findViewById<ProgressBar>(R.id.pbJobTime)
val btnStartJob = view.findViewById<Button>(R.id.btnStartJob)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val jobLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.job_layout, parent, false)
return ItemViewHolder(jobLayout)
}
var currentProgress: Int = 0
var counter: Int=0
var isTriggered: Boolean = false
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.tvJobName.text = item.dcJobName
holder.tvJobTime.text = item.dcJobTime.toString()+"s"
holder.tvJobReward.text = "$"+item.dcJobReward.toString()
val maxAllowable=25
val mills = (1000/maxAllowable)*item.dcJobTime
holder.btnStartJob.setOnClickListener{
val jobHandler = Handler()
val jobRunnable: Runnable = object : Runnable {
override fun run() {
counter++
if (counter<=maxAllowable){
currentProgress-=100/maxAllowable
holder.pbJobTime.progress = currentProgress
jobHandler.postDelayed(this, mills.toLong())
} else {
counter = 0
isTriggered=false
}
}
}
if (!isTriggered) {
currentProgress=100
holder.pbJobTime.progress = currentProgress
isTriggered=true
jobHandler.post(jobRunnable)
}
}
}
override fun getItemCount() = dataset.size }

RecyclerView的意义在于,您有一些ViewHolders可以重复使用(回收(,以显示列表中的所有项目。因此,在任何给定的时间,一个特定的VH可以代表任何任意的项目。但您的可运行程序(与特定于项目绑定(正在更新特定于ViewHolder,因此即使它实际上没有显示该项目,它也会随着该项目的进度而更新。

所以你正在寻找一种绕过这一点的方法,对吧?你可以试着找出某个特定的VH是否显示了该特定的项目,如果是的话,你可以更新它——但这非常混乱,可能会变得非常复杂(你没有取消现有的可运行程序,对吧?(,你可能会遇到一些尴尬的错误。


就我个人而言,我建议将其分解为几个单独的部分:

  • 您的数据和基本回收器视图
  • 保存正在运行的项目及其当前进度状态的内容
  • 就像你的Runnable;ticks";每隔一段时间,更新进度状态,并告诉RecyclerView更新并显示当前进度

;当前进度状态";可能只是Item的映射->进步当你开始一个作业时,将该项目及其初始进度添加到地图中(这将清除任何当前进度,如果不是你想要的,你可以绕过它(。如果尚未运行,则启动处理程序

处理程序的可运行程序只需迭代映射,更新每个项目的进度,如果它已过期,则将其从映射中删除,并在Adapter上调用notifyItemChanged(这样它就可以用当前进度重新绘制(。理想情况下,如果映射为空(即没有要继续更新的作业(,则处理程序将停止。

onBindViewHolder中的显示代码可以检查该地图,查看它显示的项目是否有进度值,如果有,则显示该值,否则显示"进度";没有正在运行的作业";state(请记住,您需要更新所有内容,因为ViewHolder以前可能显示过其他状态(


我希望这是有意义的——与多个Runnable做自己的事情相比,让一个Runnable任务每隔一段时间进行一次并更新当前状态要容易得多。拥有一个关于你的工作及其状态的单一数据源,可以更容易地更新它们(并执行保持该状态等操作(。必要时,通过参考数据源,让RecyclerView更新自己的显示,可以更容易地管理显示的数据,而不必担心内部细节,如哪些ViewHolder对象可见,以及它们当前代表的项目

最新更新