在没有 NotifyDatasetChange() 的情况下更新定时器上 RecyclerView 适配器中的 TextView

Updating TextView in RecyclerView Adapter on Timer without NotifyDatasetChange()

我的用例非常简单,我有一个 RecyclerView 并且 RecyclerView 中的每个项目都有一个计时器,它应该 运行 倒计时到 10 秒(例如)并每秒更新 ViewHolder 中的 TextView 以显示剩余时间(以秒为单位)。

我创建了一个计时器 class 如下

public class BurnTimerTask2
    {
        private System.Timers.Timer t = new System.Timers.Timer(1000);
        private int Secs;
        private TextView tv;
        public BurnTimerTask2(int Secs, TextView tv)
        {
            this.Secs = Secs;
            this.tv = tv;
            t.Elapsed += T_Elapsed;
            t.Start();
        }

        private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Android.Util.Log.Debug("PMBurnTimers", "Timer: " + Secs);
            Secs--;
            tv.Text = Secs + " Seconds left";
            if (Secs == 0)
                t.Stop();
        }
    }

在我的OnBindViewHolder中,我是这样称呼它的

if (!MYLIST[position].TimerTriggered)
{                                       
  MYLIST[position].TimerTriggered= true;
  new BurnTimerTask2(10, viewHolder.Textview);
}
else
{                   
  viewHolder.Textview.Text = "TIMER ALREADY TRIGGERED";                                      
}

new BurnTimerTask2(10, viewHolder.Textview); 是我调用计时器 class 并传递 TextView 的地方(在上面的代码中,我正在检查计时器是否已被触发,如果它有被触发,我没有调用计时器 class 所以我没有为同一个项目设置多个计时器)

问题:

1- TextView 显示秒数不会更新,除非我稍微滚动 RecyclerView ,一旦我稍微滚动 RecyclerView 它就会开始滴答并更新 [=14 的文本=] 符合预期。

2- 一旦定时器 class 被调用,我的 Activity 中的 UI 就没有响应,我无法与 RecyclerView 之外的任何东西交互几秒钟,当我可以时,它是如此之慢,如果我单击一个按钮,则该按钮上的操作需要很长时间才能触发。 (注意: 这只会在我更新 TextView 时发生,如果我不更新 TextView 和 运行 计时器本身,一切正常很好所以definalty不是导致它的计时器而是从导致它的计时器更新TextView

显然我没有以正确的方式更新 TextView。我尝试了以下

1- 运行 适配器内的计时器(相同问题)

2- 为此处指出的 ViewHolder 内的每个项目创建一个计时器 (相同的问题)

根据以下文章,我所做的应该只是简单的工作,但没有 How to handle multiple countdown timers in RecyclerView?https://github.com/Manikkumar1988/TimerInRecyclerView

我不确定如何解决这个问题。任何想法

嗨,我有一个使用 Chronometer 的想法 (https://developer.android.com/reference/android/widget/Chronometer)。它是 TextView 的子项,但会自行处理计数和更新视图。

想法是让你的列表的 viewHolder 持有这个 Chronometer,然后在你的 onBindViewHolder() 中让这个 Chronometer 计算正确的时间(如果每个项目计算不同的时间)。

试试这个适配器,我为列表中的每个项目都有一个单独的计时器,我将在 onBindViewHolder 上将该计时器绑定到 Chronometer 中。尝试看看是否可以使用计时器 class.

替换 myTimers[]

public class SOAdapter extends RecyclerView.Adapter<SOAdapter.ViewHolder> {

    Context context;
    int timerNumber;
    Chronometer[] myTimers;
    SOAdapter(Context context, int timerNumber){
        this.context = context;
        this.timerNumber = timerNumber;
        this.myTimers = new Chronometer[timerNumber];
        for (int i = 0; i < timerNumber; i++){
            Chronometer c = new Chronometer(context);
            c.setTextSize(30);
            c.setBase(SystemClock.elapsedRealtime());
            c.start();
            myTimers[i] = c;
        }
    }

    @NonNull
    @Override
    public SOAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        Chronometer timer = new Chronometer(context);
        timer.setLayoutParams(new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        timer.setTextSize(30);
        timer.setBase(SystemClock.elapsedRealtime());
        timer.start();
        return new ViewHolder(timer);
    }

    @Override
    public void onBindViewHolder(@NonNull SOAdapter.ViewHolder holder, int position) {
        Chronometer cur = myTimers[position];
        holder.bindTimer(cur);
    }

    @Override
    public int getItemCount() {
        return timerNumber;
    }


    public class ViewHolder extends RecyclerView.ViewHolder{
        Chronometer displayTimer;
        ViewHolder(Chronometer timer) {
            super(timer);
            displayTimer = timer;
        }

        public void bindTimer(Chronometer timer){
            displayTimer.setBase(timer.getBase());
        }
    }
}