在编程过程中我们尝尝会碰到使用定时器的情况,有两个场景比较常见:
一个是倒计时,时间终了做某些事情;
一个是指定时间间隔,时间到了做某些事情。
这两种场景都可以使用定时器来实现,下面就简单整理一下Android中几种常见的定时器的实现方式。

1. Timer与TimerTask

这种组合主要依赖于Timerschedule()方法。我们实现一个定时任务,定时器会在合适的时间调度我们的任务去执行。
常用的几种调度方法如下:

// 指定时间 when 到达时执行任务 task
public void schedule(TimerTask task, Date when)
// 延时 delay 毫秒之后执行任务 task
public void schedule(TimerTask task, long delay)
// 延时 delay 毫秒之后每隔 period 毫秒执行一次任务 task
public void schedule(TimerTask task, long delay, long period)
// 指定时间 when 到达时每隔 period 毫秒执行一次任务 task
public void schedule(TimerTask task, Date when, long period)

示例:

功能:延时1秒之后每隔1秒执行一次任务

long mDelay = 1000, mPeriod = 1000;
Timer mTimer = new Timer();
TimerTask mTask = new TimerTask() {    
    @Override public void run() {    
         // todo("老司机带带我~");
    }    
}; 
mTimer.schedule(mTask, mDelay, mPeriod);

2. CountDownTimer

Android系统为我们封装好的一个倒计时类就是 CountDownTimer,可以更加方便我们的使用,不过我们在创建实例的时候需要实现它的两个抽象方法 onTick() 和 onFinish()。
主要涉及的方法如下:

// 构造函数
// millisInFuture:总共时间的毫秒数;
// countDownInterval:每次触发onTick()时间间隔的毫秒数
public CountDownTimer(long millisInFuture, long countDownInterval) 
// 抽象函数 - 每到时间间隔的回调
public abstract void onTick(long millisUntilFinished);
// 抽象函数 - 总时间结束时的回调
public abstract void onFinish();

示例:

功能:每隔1秒执行一次任务

CountDownTimer mCDTimer = new CountDownTimer(10000, 1000) {  
    @Override public void onTick(long millisUntilFinished) {  
        // todo("秀恩爱~");
    }  
    @Override public void onFinish() {  
        // todo("死的快~");
    }
}
mCDTimer.start();   // 开始计时

3. AlarmManager

AlarmManager 是 Android 中常用的一种系统级别的提示服务,我们设定一个时间,然后在该时间到来时,AlarmManager 为我们广播一个我们设定的 Intent 去执行指定的动作。
主要涉及的方法如下:

// 用于设置一次性闹钟
// 第一个参数:闹钟类型,第二个参数:闹钟执行时间,第三个:表示闹钟响应动作
public void set(int type, long triggerAtMillis, PendingIntent operation)
// 用于设置重复闹钟
// 第一个参数:闹钟类型,第二个参数:闹钟首次执行时间,第三个参数:闹钟两次执行的间隔时间,第四个参数:闹钟响应动作
public void setRepeating(int type,long startTime,long intervalTime,PendingIntent pi)
// 通过启动<服务>来实现闹钟提示
public static PendingIntent PendingIntent.getService(Context context,int requestCode,Intent intent,int flags)
// 通过启动<广播>来实现闹钟提示
public static PendingIntent PendingIntent.getBroadcast(Context context,int requestCode,Intent intent,int flags)
// 通过启动<活动>来实现闹钟提示
public static PendingIntent PendingIntent.getActivity(Context context,int requestCode,Intent intent,int flags)

示例:

功能:每隔1秒执行一次任务

// 设置 AlarmManager
@Override 
public void onCreate(Bundle savedInstanceState) { 
    ...
    // 创建 Intent 对象 
    Intent intent = new Intent("ACTION_ALARM_PER_SECOND");  
    intent.putExtra("MESSAGE","浪ing...");     
    // 获取 PendingIntent 对象 
    PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0);    
    // 获取 AlarmManager 对象(系统级服务)  
    AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);    
    // 设置闹钟从当前时间开始,每隔1秒执行一次 PendingIntent 对象
    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000, pi);
    ...
}
// 自定义 BroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {  
    @Override public void onReceive(Context context, Intent intent) {  
        String msg = intent.getStringExtra("MESSAGE");  
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();  
    }  
}
// 在 Manifest.xml 中注册 MyBroadcastReceiver
<receiver android:name=".MyBroadcastReceiver">  
        <intent-filter>  
            <action android:name="ACTION_ALARM_PER_SECOND" />  
        </intent-filter>  
</receiver>

4. Handler与Message

细心的人可能发现了,上面 CountDownTimer 的内部实现使用的就是 Handler 和 sendMessageDelayed() 的方法。
主要涉及的方法如下:

public final boolean sendEmptyMessageDelayed(int what, long delayMillis);
public final boolean sendMessageDelayed(Message msg, long delayMillis);

示例:

功能:每隔1秒执行一次任务

// 发送消息
@Override 
public void onCreate(Bundle savedInstanceState) { 
    ...          
    handler.sendMessageDelayed(0, 1000);    
    ...
}
// 定义 Handler 接收消息并再次发送
Handler mHandler = new Handler(){    
    public void handleMessage(Message msg) {           
        switch (msg.what) {    
            case 0:        
                // todo("洪湖水,浪打浪");
                handler.sendMessageDelayed(message, 1000);
                break;     
        }    
        super.handleMessage(msg);    
    }    
};

5. Handler与Runnable

使用 Handler 与 Runnable 的组合我们也可以实现一个定时器,并且定时器是在 Runnable 线程中执行,并不会影响 UI 操作。
示例:

功能:每隔1秒执行一次任务

// 发送消息
@Override 
public void onCreate(Bundle savedInstanceState){    
    ...
    handler.postDelayed(mRunnable, 1000); 
    ...   
}       
// 定义 Runnable 接收消息并再次发送
Handler mHandler = new Handler();    
Runnable mRunnable = new Runnable() {    
    @Override public void run() {    
        // todo("门前大桥下,游过一群鸭");
        handler.postDelayed(this, 1000);    
    }    
};

6. Handler与Thread

使用 Handler 与 Thread 的组合我们也可以实现一个定时器,并且定时器是在 Runnable 线程中执行,并不会影响 UI 操作。
示例:

功能:每隔1秒执行一次任务

// 发送消息
@Override 
public void onCreate(Bundle savedInstanceState){    
    ...
    // start thread
    new Thread(new MyThread()).start();             
}       
// 定义 Handler 接收消息
Handler handler = new Handler(){ 
public void handleMessage(Message msg){    
    switch (msg.what) {    
        case 1: 
            // todo("快来快来数一数,二四六七八");
            break;
    }    
    super.handleMessage(msg); 
};    
// 定义 MyThread 循环发送信息
public class MyThread implements Runnable {   
    @Override public void run(){    
        while(true) {    
            try {    
                Thread.sleep(1000);        
                Message message = new Message();    
                message.what = 1;    
                handler.sendMessage(message);    
            } catch (Exception e) {    
                e.printstacktrace();
            }   
        }
    }
}