问题描述
我试图建立某种顺序倒计时。意思是,我建立的演习,每一个包含一个特定的时间,这是倒计时时间的队列。在自定义倒计时类,我弹出这些演习从队列和使用的持续时间进行倒计时。
我希望这些倒数运行此起彼伏。为此,我建立了一个倒计时类,基于抽象类 CountDownTimer
的code的基础上。
I was trying to build some sort of sequential countdown. Meaning, that I build up a queue of "exercises", each one containing a specific duration, which is the countdown time. In a custom Countdown class, I pop these exercises off the queue and use the duration as countdown.I want these countdowns to run one after another. For this I built a Countdown class, based on the code basis of the abstract class CountDownTimer
.
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<Exercise> eq;
private long mMillisInFuture;
private int mCountdownInterval;
private String name;
private long mStopTimeInFuture;
CountdownHandler cHandler;
public ExerciseMeCountDownTimer(ArrayList<Exercise> elist,
Button startStopButton, TextView countdownText,
CountdownHandler cHandler) {
this.cHandler = cHandler;
eq = new ArrayDeque<Exercise>(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
,然后,应更新一个TextView。
The important part is the sendMessage
part, where I send the time left on the countdown to a handler
of my MainActivity
, which then, should update a 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);
}
}
最后更新的TextView
在 MainActivty
public void sayLog(String text) {
countdown.setText(text);
}
ExerciseMeCountDownTimer由
ExerciseMeCountDownTimer is called by
new ExerciseMeCountDownTimer(elist, cHandler);
这是一些的onClick()。
on some onClick().
的问题是,有时(实际上大部分时间)不更新TextView的正常。它停止更新的随机时间像00:05:211等。
会有人能告诉我这是为什么持续发生?也许还加入了解决方案,或者至少一些文献(也许指出了部分路段),我应该阅读理解问题?我也为UPEN替代方法,因为我是新来这个处理程序在Android中,线程的事情。
The problem is, that sometimes (actually most of the time) the textView is not updated properly. It stops updating on random times like 00:05:211 etc.Would anyone mind telling me why this is keeps happening? Maybe also adding a solution or at least some literature (maybe pointing out some sections) which I should read to understand the problem? I am also upen for alternative approaches, as I am new to this "handler", "threads" thing in android.
修改
- TextView的正在更新,但是TextView的是点击。每当我点击了它的TextView停止更新!
- 作为公认的答案显示,我决定使用更新
onTick()
方法内适当的TextView的DIREKT方法。
- the textview was updating, but the textview was clickable. Whenever I clicked on the textview it stopped updating!
- as the accepted answer shows, I decided to use the direkt approach of updating the appropriate textview inside the
onTick()
method.
推荐答案
使用处理程序
,事情在这种情况下是使它过于复杂。
Using Handler
and things in this situation is making it overly complicated.
CountDownTimer
取值 onTick()
和 onFinish()
在 UI线程都运行
所以更新 TextViews
等查看
期从任何一种方法可以很容易地只是路过查看
的参考类的构造函数中完成,因为你已经在做。然后,你只需在需要的方法更新它。
CountDownTimer
s onTick()
and onFinish()
both run on the UI Thread
so updating TextViews
and other View
s from either method can be done easily just by passing a reference of the View
to the constructor of the class, as you are already doing. Then you simply update it in the method needed.
// could create a member variable for the TextView with your other member variables
...
mTV;
然后在构造函数中给它分配
//删除了对处理器 - 你已经提到这里的TextView
公共ExerciseMeCountDownTimer(ArrayList的ELIST,
按钮startStopButton,TextView的countdownText){
MTV = countdownText;
then in your constructor assign it // removed reference to Handler--you already have reference to TextView here public ExerciseMeCountDownTimer(ArrayList elist, Button startStopButton, TextView countdownText) { mTV = countdownText;
然后更新任何需要的方式
then update in whichever method is needed
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();
}
这篇关于连续countdowntimer与处理程序不会更新的TextView正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!