有三种实现计时器的方式:
1:最基本的Handler+Thread的方式,因为最近准备着手了解线程和消息机制,所以这一个会比较详细。
2:handler.postDelayed()方法,这个实现起来是最简单的,但是个人不太喜欢,因为递归这种东西,真的很难写。
3:Thread+TimeTask的方式; 其实这三个,最基础的是第一种。本文介绍的也是第一种,之后两种会在之后的blog里面贴上代码,不仔细介绍了。当然,也许还有其他的,我不知道罢了。
布局文件activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="fatenliyer.f_TimerOne.MainActivity" >
<TextView
android:id="@+id/tv_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="40sp" >
</TextView>
</RelativeLayout>
配置文件AndroidMainfest不需要做处理
第一个就是MainActivity.java ; 这里的作用就是 执行OnCreate方法,然后,开启一个线程
package fatenliyer.f_TimerOne;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
/**
* 计时器,每秒钟增加 1
*/
public class MainActivity extends Activity {
public static final int TIMER = 1;
private TextView tvShow;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvShow = (TextView) findViewById(R.id.tv_one);
new Thread(new TimeThread(tvShow)).start();
}
}
接下来就是TimeThread线程; 这里新建了一个TimeHandler的消息处理机制,即每次sleep1000ms之后,就将一个消息传给handler,并且是永恒执行的(while(true))。当然,退出主线程也就会结束此子线程
package fatenliyer.f_TimerOne;
import android.os.Message;
import android.widget.TextView;
/**
* 线程, 计时线程
*/
public class TimeThread implements Runnable{
private TimeHandler mHandler = new TimeHandler();
private TextView mTv;
public TimeThread(TextView tv) {
this.mTv = tv;
}
@Override
public void run() {
while(true){ // 这句话 表明一直执行
try {
Thread.sleep(1000); // 1000 ms
Message msg = new Message();
msg.what = MainActivity.TIMER;
msg.obj = mTv;
mHandler.sendMessage(msg);
System.out.println("send...");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("thread error...");
}
}
}
}
接下来就是最后一块Handler。 这里比较长的是changeTimerFormat,但是不用管它,它只是将秒数,转化成好看一点的字符串罢了。主要的还是 handlermessage(),是在这里确定了msg.what,然后取出msg.obj,并且执行显示到界面上的。
package fatenliyer.f_TimerOne;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
/**
* 计时器 的消息处理
*/
public class TimeHandler extends Handler{
private long i = 0;
private TextView mTv;
TimeHandler(){
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MainActivity.TIMER) {
mTv = (TextView) msg.obj;
mTv.setText(changeTimerFormat(++i));
}
}
/**
* 转化成显示的格式
* @param paramLong
* @return 待显示的字符串
*/
private String changeTimerFormat(long paramLong)
{
long day = paramLong / 86400;
long hour = paramLong % 86400 / 3600;
long minute = paramLong % 3600 / 60;
long second = paramLong % 60;
// 天数
String str1 = String.valueOf(day);
if (day == 0) {
str1 = "";
}else{
str1 = str1 + "天";
}
// 小时数
String str2 = String.valueOf(hour);
if (hour == 0) {
str2 = "";
}else if (hour < 10) {
str2 = "0" + str2 + ":";
}else {
str2 = str2 + ":";
}
// 分钟数
String str3 = String.valueOf(minute);
if (minute == 0) {
str3 = "00" + ":";
}else if (minute < 10) {
str3 = "0" + str3 + ":";
}else {
str3 = str3 + ":";
}
// 秒钟数
String str4 = String.valueOf(second);
if (second == 0) {
str4 = "";
}else if (second < 10) {
str4 = "0" + str4;
}
return str1 + str2 + str3 + str4;
}
}
好了,代码就这样结束了。
总结一下,这个计时器的工作过程:
1,在MainActivity中开启一个线程,也就是TimerThread
2,在线程的run方法中,执行休眠1000ms, 并且休眠一次就传递一次消息给handler,然后由hander更新UI。
OK,这样我们也就容易理解Handler和Thread扮演的角色了:
Thread就好像是包身工,只管不停的做自己的事,然后,隔段时间就告诉包工头一次,告诉的方式就是msg,
Hander就是包工头,他就通过msg.what来确定是哪个包身工做的事, 通过msg.obj获得成品.
图片效果:
代码下载:
http://download.csdn.net/detail/u014803950/8656227