带处理程序的顺序countdowntimer不会正确更新textView

我试图建立某种顺序倒计时。 意思是,我建立了一个“练习”队列,每个练习都包含一个特定的持续时间,即倒计时时间。 在自定义的Countdown类中,我将这些练习从队列中弹出并将持续时间用作倒计时。 我希望这些倒计时一个接一个地运行。 为此,我根据抽象类CountDownTimer的代码基础构建了一个Countdown类。

 import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Locale; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.widget.Button; import android.widget.TextView; public class ExerciseMeCountDownTimer { private static final int MSG_COUNTDOWN = 100; private static final int MSG_FINISH = 99; private ArrayDeque eq; private long mMillisInFuture; private int mCountdownInterval; private String name; private long mStopTimeInFuture; CountdownHandler cHandler; public ExerciseMeCountDownTimer(ArrayList elist, Button startStopButton, TextView countdownText, CountdownHandler cHandler) { this.cHandler = cHandler; eq = new ArrayDeque(elist); this.start(); } public final void cancel() { mHandler.removeMessages(MSG); } private synchronized final ExerciseMeCountDownTimer start() { if (!eq.isEmpty()) { Exercise e = eq.pop(); this.mMillisInFuture = Long.parseLong(e.getDuration()); this.mCountdownInterval = 30; this.name = e.getName(); } else { onFinish(); return this; } if (mMillisInFuture <= 0) { onFinish(); return this; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return this; } public void onTick(long millisUntilFinished) { Message msg = cHandler.obtainMessage(MSG_COUNTDOWN); Bundle data = new Bundle(); String text = String.format(Locale.GERMANY, "%02d:%02d:%03d", millisUntilFinished / 100000, millisUntilFinished / 1000, millisUntilFinished % 1000); data.putString("countdown", text); msg.setData(data); cHandler.sendMessage(msg); } public void onFinish() { if (!eq.isEmpty()) { this.start(); } Message msg = cHandler.obtainMessage(MSG_FINISH); Bundle data = new Bundle(); String text = String.format(Locale.GERMANY, "00:00:000"); data.putString("finish", text); msg.setData(data); cHandler.sendMessage(msg); } private static final int MSG = 1; // handles counting down private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { // no tick, just delay until done sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); onTick(millisLeft); // take into account user's onTick taking time to // execute long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); // special case: user's onTick took more than interval // to // complete, skip to next interval while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay); } } }; @Override public String toString() { return this.name; } } 

重要的部分是sendMessage部分,我将倒计时剩余的时间发送给我的MainActivityhandler ,然后应该更新textview。

 import android.os.Handler; import android.os.Message; class CountdownHandler extends Handler { private static final int MSG_COUNTDOWN = 100; private static final int MSG_FINISH = 99; private MainActivity mActivity; CountdownHandler(MainActivity activity) { this.mActivity = activity; } @Override public void handleMessage(Message msg) { if (msg.what == MSG_COUNTDOWN) { String text = msg.getData().getString("countdown"); this.mActivity.sayLog(text); } if (msg.what == MSG_FINISH) { String text = msg.getData().getString("finish"); this.mActivity.sayLog(text); } } 

最后更新MainActivty中的MainActivty

 public void sayLog(String text) { countdown.setText(text); } 

ExerciseMeCountDownTimer被调用

 new ExerciseMeCountDownTimer(elist, cHandler); 

在一些onClick()上。

问题是,有时(实际上大部分时间)textView没有正确更新。 它停止随机时间更新,如00:05:211等。有人会介意告诉我为什么这种情况一直在发生? 也许还要添加一个解决方案或至少一些文献(可能指出一些部分)我应该阅读以理解问题? 我也是替代方法,因为我是android中的“处理程序”,“线程”的新手。

编辑

  • textview正在更新,但textview是可点击的。 每当我点击textview时它就会停止更新!
  • 如接受的答案所示,我决定使用direkt方法更新onTick()方法中的相应textview。

在这种情况下使用Handler和东西使它变得过于复杂。

CountDownTimeronTick()onFinish()都在UI Thread上运行,因此只需将View的引用传递给类的构造函数就可以轻松地从任一方法更新TextViews和其他View ,就像您已经在做的那样。 然后,您只需在所需的方法中更新它。

 // could create a member variable for the TextView with your other member variables ... mTV; 

然后在你的构造函数中分配//删除对Handler的引用 – 你已经在这里引用了TextView public ExerciseMeCountDownTimer(ArrayList elist,Button startStopButton,TextView countdownText){mTV = countdownText;

然后以任何需要的方法更新

 public void onTick(long millisUntilFinished) { String text = String.format(Locale.GERMANY, "%02d:%02d:%03d", millisUntilFinished / 100000, millisUntilFinished / 1000, millisUntilFinished % 1000); mTV.setText(text); // set the text here } public void onFinish() { if (!eq.isEmpty()) { this.start(); }