加快启动对象速度并更快地更新TextView。

huangapple go评论71阅读模式
英文:

Start objects faster and update Textview faster

问题

我想创建多个定时器。
我在MainActivity中的一个ArrayList中初始化这些定时器。然后将它们添加到RecyclerView中以便显示出来。为了开始,我通过一个for循环遍历并执行每个单独对象的startTimer()方法。
不幸的是,每个定时器的时间不正确。这意味着一个定时器运行得更快,第二个运行得更慢,依此类推。因此,每个定时器在不同的时间启动,或者文本在不同的时间更改。

我的问题是,是否有其他方法可以启动定时器并更改TextView中的文本,以便GUI更新更快,程序本身运行更快?
目标应该是所有定时器都同样快,没有延迟。提前感谢您的回答!

MainActivity

timerList= new ArrayList<>();
for (int i = 1; i <= 10; i++) {
    timerList.add(new Timer(i, 600000 * i)); // 每个定时器有不同的时间
}

recyclerView.setLayoutManager(recyclerViewLayoutManager);
adapter = new TimerAdapter(this, timerList);

recyclerView.setAdapter(adapter);
context = this;

button_start.setOnClickListener(v -> {

    for (Timer timer: timerList) {
        timer.startTimer();
    }
});

@Override
public void updateMyText(int index, long time) {
    timerList.get(index-1).setTime(time);
    adapter.notifyDataSetChanged();
}

Timer

public interface MyCallback {
    public void updateMyText(int index, long time);
}

public Timer(int index, long startTimeMilliseconds) {
    this.index = index;
    this.time = startTimeMilliseconds;
    mTimeLeftInMillis = startTimeMilliseconds;
    startTime = startTimeMilliseconds;
}

public void startTimer() {
    mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            mTimeLeftInMillis = millisUntilFinished;
            updateCountDownText();
        }
        @Override
        public void onFinish() {
            mTimerRunning = false;
        }
    }.start();
    mTimerRunning = true;
}

public void resetTimer() {
    mCountDownTimer.cancel();
    mTimerRunning = false;
    mTimeLeftInMillis = startTime;
    timeLeftFormatted = formattedTime(startTime);
    changeText(index-1);
}

public void updateCountDownText() {
    if(myCallback != null) {
        myCallback.updateMyText(getIndex(), mTimeLeftInMillis);
    }
}

希望这些信息对您有所帮助。如果您需要进一步的帮助,请随时提问。

英文:

I want to create multiple timers.
I initialize this in an ArrayList in the MainActivity. These are then added in a ReyclerView so that they are also displayed. To start, I go through a for loop and execute the startTimer () method for each individual object.
Unfortunately, the times are not correct for every timer. That means one timer is faster, the second is slower and so on. So each timer starts at different times or the text changes at different times.

My question now is, are there other approaches to start the timers and change the texts in the TextView so that the GUI is updated faster and the program itself runs faster?
The goal should be that all timers are equally fast and there is no delay. Thanks in advance. Looking forward to answer!

MainActivity

     timerList= new ArrayList&lt;&gt;();
        for (int i = 1; i &lt;= 10; i++) {
            timerList.add(new Timer(i, 600000 * i))); // 
Each timer has a different time
        }
    
        recyclerView.setLayoutManager(recyclerViewLayoutManager);
        adapter = new TimerAdapter(this, timerList);
    
        recyclerView.setAdapter(adapter);
        context = this;
    
    
        button_start.setOnClickListener(v -&gt; {
    
                for (Timer timer: timerList) {
                    timer.startTimer();
                
    
        });
    
    @Override
    public void updateMyText(int index, long time) {
        timerList.get(index-1).setTime(time);
        adapter.notifyDataSetChanged();
    }

Timer

public interface MyCallback {
    public void updateMyText(int index, long time);
}
   public Timer(int index, long startTimeMilliseconds) {
        this.index = index;
        this.time = startTimeMilliseconds;
        mTimeLeftInMillis = startTimeMilliseconds;
        startTime = startTimeMilliseconds;
    }



    public void startTimer() {
        mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                mTimeLeftInMillis = millisUntilFinished;
                updateCountDownText();
            }
            @Override
            public void onFinish() {
                mTimerRunning = false;
            }
        }.start();
        mTimerRunning = true;
    }

    public void resetTimer() {
        mCountDownTimer.cancel();
        mTimerRunning = false;
        mTimeLeftInMillis = startTime;
        timeLeftFormatted = formattedTime(startTime);
        changeText(index-1);
    }

    public void updateCountDownText() {
        //MainActivity.timerList.get(getIndex()-1).setTime(mTimeLeftInMillis);
        //MainActivity.adapter.notifyDataSetChanged();
        if(myCallback != null) {
            myCallback.updateMyText(getIndex(), mTimeLeftInMillis);
        }
    }

答案1

得分: 2

使用LiveData和数据绑定或MVVM设计模式。您无需担心视图的更快更新操作。

英文:

Use Live Data and Binding or MVVM design pattern. You don't have to worry about faster update operation of views.

答案2

得分: 1

代码部分不需要翻译,以下是翻译好的部分:

  1. 使计时器类仅存储计时器的开始时间和应显示的时间字符串,不要在其中创建CountDownTimer。

    反之,在其中创建一个名为“updateTimer()”的方法,用于根据当前时间和计时器的开始时间更新字符串。

  2. 在您的Activity中使用一个单一的CountDownTimer,遍历计时器列表,并在每个计时器上调用updateTimer(),并在循环结束时调用adapter.notifyDataSetChanged()。

这将使所有视图一起更新,消除使用多个CountDownTimer的低效率,并且每秒仅调用adapter.notifyDataSetChanged()一次(与您拥有的计时器数量不同 - 每秒一次)。

英文:

The reason the code you wrote works slowly (and time isnt updated on all views together), is because you are creating a separate CountDownTimer for each of your timers.

You dont have to do that. All you need to do is have a single CountDownTimer, that runs every second and updates all of your views simultaneously.

  1. Make Timer class only store the start time of the timer, and a string with the time it should show, dont create a CountDownTimer inside it.

    Instead create a method inside it - "updateTimer()" for updating the string, based on
    the current time and the start time of the counter.

  2. Using a single CountDownTimer in your Activity, loop through the list of timers and call updateTimer() on each of your timers, and call adapter.notifyDataSetChanged() when the loop is done.

This will make all your views update together, remove the inefficiency of using multiple CountDownTimers, and only call adapter.notifyDataSetChanged() once every second (as opposed to the amount of timers you have - every second)

答案3

得分: 1

我认为主要问题是指令的顺序执行,添加Threads概念可能会解决这个问题,我认为Threads多线程将允许计时器同时启动,并且代码执行的任何更新或其他指令都不会影响已经运行的代码。

多线程指的是在单个程序内并发执行两个或多个任务。教程

现在,要在尽可能相同的时间启动线程,我们可以使用CyclicBarrier

// 我们想要同时启动10个线程,但让我们从button_start点击线程来控制时间。这就是为什么我们有11个“parties”而不是10个。
final CyclicBarrier gate = new CyclicBarrier(11);
button_start.setOnClickListener(v -> {
    for (Timer timer : timerList) {
        new Thread() {
            public void run() {
                gate.await(); // 等待门打开
                timer.startTimer();
            }
            // 此时,所有的10个计时器都被阻塞在门上。
            // 因为我们将“11”作为参数,所以门还没有打开。
            // 现在,如果我们在主线程上阻塞在门上,它将打开,
            // 并且所有线程都将开始执行任务!

            gate.await(); // 这是额外的第11个,将打开门
        };
    }
});

这仍然不能确保它们在标准JVM上完全同时启动,但可以接近。

如果这个解决方案有效,可以复制相同的解决方案来处理更新部分。

英文:

i think the main issue is the sequential executing of instructions, and adding Threads concept may resolve the issue ,what i think is Threads and Multi threading will allow timers to start at the same time and any updates or other instructions of code execution will not effect the already running code .

> Multi threading refers to two or more tasks executing concurrently within a single program. Tutorial

now To start the threads at exactly the same time (at least as good as possible),we can use a CyclicBarrier:

 // We want to start just 10 threads at the same time, but let&#39;s control that 
 // timing from the button_start click thread. That&#39;s why we have 11 &quot;parties&quot; instead 
 //of 10.
 final CyclicBarrier gate = new CyclicBarrier(11);
 button_start.setOnClickListener(v - &gt; {
             for (Timer timer: timerList) {
                 new Thread() {
                     public void run() {
                         gate.await(); // waiting for the gate to open
                         timer.startTimer();
                     }
                     // At this point, all the 10 timers are blocked on the gate. 
                     // Since we gave &quot;11&quot; as the argument, gate is not opened yet.
                     // Now if we block on the gate from the main thread, it will open
                     // and all threads will start to do stuff!

                     gate.await(); // this is the extra 11th which will open the gate

                 };

This still can't make sure that they are started exactly at the same time on standard JVMs, but you can get pretty close.

replicate the same solution if it works , for the update part

huangapple
  • 本文由 发表于 2020年8月5日 21:12:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/63265958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定