如何用线程构建Android定时器应用程序?
问题描述:
我正在尝试为Android创建一个简单的锻炼计时器。用户创建一个包含总持续时间,总休息时间等信息的WorkoutPlan
,应用程序将显示一个每秒更新一次的计时器。如何用线程构建Android定时器应用程序?
很简单的开始,但我试图尽可能正确地,即关注,正确的技术,反应灵敏的用户界面,保证了计时器将被准确的分离构建应用程序等
这里有一个什么我迄今为止的简化:
WorkoutPlan
,用户可以加载/不同的锻炼计划保存到计时器
public class WorkoutPlan {
public long duration;
}
TimerThread
,这个类实现Runnable
,它取在启动/停止构造函数中,在WorkoutPlan
中显示已用时间。
public class TimerThread implements Runnable {
public boolean running = false;
private long lastStartTime;
private long savedTime;
private WorkoutPlan plan;
private Handler handler;
public TimerThread(WorkoutPlan p, Handler h) {
plan = p;
handler = h;
}
public synchronized void start() {
lastStartTime = System.currentTimeMillis();
running = true;
}
public synchronized void pause() {
savedTime = elapsedTime();
lastStartTime = 0;
running = false;
}
public synchronized long elapsedTime() {
if (lastStartTime == 0) {
return savedTime;
} else {
return savedTime + (System.currentTimeMillis() - lastStartTime);
}
}
public synchronized String currTimeStr() {
//format elapsed time in seconds to hh:mm:ss format
long elapsed = elapsedTime()/1000;
long h = elapsed/3600;
long m = (elapsed % 3600)/60;
long s = elapsed % 60;
if (h > 0) {
return String.format("%02d:%02d:%02d", h, m, s);
} else {
return String.format("%02d:%02d", m, s);
}
}
@Override
public void run() {
while (running) {
try {
handler.sendMessage(handler.obtainMessage());
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
TimerView
,显示经过的时间
public class TimerView extends View {
private final Paint mBg;
private final Paint mText;
private WorkoutPlan plan;
private TimerThread timer;
private Thread thread;
private Handler handler = new TimerHandler();
public TimerView(Context context, AttributeSet attrs) {
super(context, attrs);
plan = new WorkoutPlan();
timer = new TimerThread(plan, handler);
thread = new Thread(timer);
mBg = new Paint();
mBg.setColor(getResources().getColor(R.color.bg_default));
mText = new Paint();
mText.setColor(getResources().getColor(R.color.text));
}
public void start() {
timer.start();
thread.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//draw current time and current round
canvas.drawText(timer.currTimeStr(), 0, 50, mText);
}
private class TimerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
invalidate();
}
}
}
最后,WorkoutTimer
自定义视图,启动它关闭
public class WorkoutTimer extends Activity {
private TimerView mTimer;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timer);
mTimer = (TimerView) findViewById(R.id.timer_view);
}
@Override
protected void onStart() {
super.onStart();
mTimer.start();
}
}
几个问题的活动:
- 哪里是创建
WorkoutPlan
对象的最佳地点?目前它在TimerView
完成。是否应该在WorkoutTimer
活动中完成?如果是的话,我如何将WorkoutPlan
对象传递给TimerView
? - 该应用第一次正常工作,但是当我进入主屏幕然后第二次回到应用时崩溃。什么导致它崩溃?它是首字母吗?
- 当前我在新的
Thread
中使用了Handler
。这是好的还是会TimerTask
更好?哪里是开始线程的最佳地点? - 我正确的把所有的线程代码放在
TimerView
?感觉他们应该在别的地方。 - 我是否正确添加同步到
TimerThread
中的所有方法? - 我试图创建这个应用程序,因为我可以练习。请让我知道,如果我应该做的技术有所改进,或者如果我做了不正确的事情。
答
如果你问的是风格,很糟糕的风格是在某些变体中使用“计时器”这个词来实现不是Timer,而是完全不同的类Handler。使用一些其他的名字。现在代码几乎是不可读的。