带处理程序的顺序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
部分,我将倒计时剩余的时间发送给我的MainActivity
的handler
,然后应该更新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
和东西使它变得过于复杂。
CountDownTimer
的onTick()
和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(); }