Android 定时器AlarmManager
发布日期:2021-11-12 07:57:35 浏览次数:21 分类:技术文章

本文共 6264 字,大约阅读时间需要 20 分钟。

原文地址:http://blog.csdn.net/aqi00/article/details/50525067

Timer和TimerTask

Java中的定时器机制有现成的方案,就是Timer+TimerTask。其中TimerTask用来描述时刻到达后的事务处理,而Timer用来调度定时任务,如何时启动、间隔多久再次运行等等。
Timer的调度方法是schedule,主要有三个参数。第一个参数表示用来调度的定时任务,第二个参数表示延迟多久首次启动任务,第三个参数表示间隔多久再次启动任务。
public void schedule(TimerTask task, long delay, long period)
定时任务得自己写个继承自TimerTask的新类,并重写run方法填入具体的事务处理代码。调用Timer的schedule方法,定时任务便会按照调度设置按时启动;TimerTask不能直接设置运行的次数上限,一旦启动就会持续定时运行,除非对象销毁或者调用了TimerTask的cancel方法。调用cancel方法停止定时任务后,若想重启该定时任务,只能重新声明TimerTask对象,并且重新调用schedule方法。
Timer+TimerTask的实质是利用开启Thread来触发定时任务,所以TimerTask实际上运行于非UI线程,也就无法直接操作UI。若想在TimerTask中修改UI控件,得通过Handler发送消息来间接实现。

CountDownTimer

CountDownTimer是Android提供的倒计时器,日常生活中时有见到倒计时的场景,比如说火箭发射倒计时。
通常我们要自定义一个CountDownTimer的派生类,并重写如下的三个方法:
构造函数 : 第一个参数是总的计时长度,第二个参数是每次的计时间隔(好像时钟的滴答)。
onTick : 每次计时触发的事件。
onFinish : 计时结束事件。
要想启动CountDownTimer计时,调用它的start方法即可,停止计时则调用cancel方法。另外倒计时器触发的onTick和onFinish都运行于非UI线程,所以与Timer一样,也得借助于Handler机制才能操作UI元素。

AlarmManager

AlarmManager是Android提供的一个全局定时器,其使用范围要大于Timer方式。因为Timer方式采用Thread通信,所以只适用于线程间通信,并且生命周期也有限。如果在Activity中定义Timer,那么Activity页面销毁后,定时器也失效了;如果在Application中定义Timer,那么APP退出后,定时器也要失效。相比之下,AlarmManager利用系统的提醒服务定时发送广播,所以不但适用于线程间通信,而且也适用于进程间通信。另外,由于是系统服务发送广播,因此只要再次打开APP,就会自动收到广播发来的定时任务。
AlarmManager常用的启动方法有两个:
set : 该方法用于设置一次性定时器。第一个参数表示定时器类型,第二个参数表示任务执行时间,第三个参数表示定时任务。
setRepeating : 该方法用于设置重复定时器。第一个参数表示定时器类型,第二个参数表示任务首次执行时间,第三个参数表示再次执行的间隔时间,第四个参数表示定时任务。
其中定时器类型主要取值有:
RTC_WAKEUP : 表示定时器即使在睡眠状态下也会启用,此时定时器使用系统时间
RTC : 表示定时器在睡眠状态下不可用,此时定时器使用系统时间
ELAPSED_REALTIME_WAKEUP : 表示定时器即使在睡眠状态下也会启用,此时定时器使用相对时间(相对于系统启动开始)
ELAPSED_REALTIME : 表示定时器在睡眠状态下不可用,此时定时器使用相对时间
因为AlarmManager使用的是系统服务来发送广播,所以在注册广播接收器时需要注意以下几点:
1、要在AndroidManifest.xml中定义receiver;
2、代码中注册接收器必须使用Context.registerReceiver,不能使用LocalBroadcastManager来注册;

PendingIntent

AlarmManager启动方法中的定时任务使用了PendingIntent类,PendingIntent顾名思义就是一个延迟处理的通信工具。PendingIntent的实例可通过下列三种方法得到:
getActivity : 获取用于启动页面的实例
getService : 获取用于启动服务的实例
getBroadcast : 获取用于发送广播的实例
三个方法的参数是一样的,第一个参数表示Context,第二个参数表示请求代码用于标识本次请求的唯一性,第三个参数表示Intent实例(可捆绑具体参数信息Bundle),第四个参数表示PendingIntent的启动标志,具体取值说明如下:
FLAG_ONE_SHOT : 此时启动的PendingIntent只能使用一次。
FLAG_NO_CREATE : 如果不存在描述的PendingIntent,则不会创建新任务。
FLAG_CANCEL_CURRENT : 如果已存在描述的PendingIntent,则先取消该任务再创建新任务。
FLAG_UPDATE_CURRENT : 一般用这个标志。如果已存在描述的PendingIntent,则更新而不是取消该任务。

使用示例

下面是两种定时方式的效果图:
下面是Timer、CountDownTimer和AlarmManager三种定时器的示例代码:
[java]
  1. import java.util.Timer;  
  2. import java.util.TimerTask;  
  3.   
  4. import com.example.exmthread.R;  
  5.   
  6. import android.app.Activity;  
  7. import android.app.AlarmManager;  
  8. import android.app.PendingIntent;  
  9. import android.content.BroadcastReceiver;  
  10. import android.content.Context;  
  11. import android.content.Intent;  
  12. import android.content.IntentFilter;  
  13. import android.os.Bundle;  
  14. import android.os.CountDownTimer;  
  15. import android.os.Handler;  
  16. import android.os.Message;  
  17. import android.view.View;  
  18. import android.view.View.OnClickListener;  
  19. import android.widget.Button;  
  20. import android.widget.TextView;  
  21.   
  22. public class AlarmActivity extends Activity implements OnClickListener {  
  23.   
  24.     private TextView tv_alarm;  
  25.     private Button btn_timer;  
  26.     private Button btn_counter;  
  27.     private Button btn_alarm;  
  28.   
  29.     @Override  
  30.     protected void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.activity_alarm);  
  33.   
  34.         btn_timer = (Button) findViewById(R.id.btn_timer);  
  35.         btn_counter = (Button) findViewById(R.id.btn_counter);  
  36.         btn_alarm = (Button) findViewById(R.id.btn_alarm);  
  37.         btn_timer.setOnClickListener(this);  
  38.         btn_counter.setOnClickListener(this);  
  39.         btn_alarm.setOnClickListener(this);  
  40.   
  41.         tv_alarm = (TextView) findViewById(R.id.tv_alarm);  
  42.         ALARM_EVENT = getResources().getString(R.string.alarm_event);  
  43.     }  
  44.   
  45.     @Override  
  46.     public void onClick(View v) {  
  47.         if (v.getId() == R.id.btn_timer) {  
  48.             if (mTimerTask == null) {  
  49.                 mTimerTask = new MyTimerTask();  
  50.                 Timer timer = new Timer();  
  51.                 timer.schedule(mTimerTask, 50200);  
  52.                 btn_timer.setText("停止Timer定时计数");  
  53.             } else {  
  54.                 mTimerTask.cancel();  
  55.                 mTimerTask = null;  
  56.                 btn_timer.setText("开始Timer定时计数");  
  57.             }  
  58.         } else if (v.getId() == R.id.btn_counter) {  
  59.             if (mCounterTask == null) {  
  60.                 mCounterTask = new MyCounter(80001000);  
  61.                 mCounterTask.start();  
  62.                 btn_counter.setText("停止CountDownTimer定时计数");  
  63.             } else {  
  64.                 mCounterTask.cancel();  
  65.                 mCounterTask = null;  
  66.                 btn_counter.setText("开始CountDownTimer定时计数");  
  67.             }  
  68.         } else if (v.getId() == R.id.btn_alarm) {  
  69.             if (alarmReceiver == null) {  
  70.                 alarmReceiver = new AlarmReceiver();  
  71.                 IntentFilter filter = new IntentFilter(ALARM_EVENT);  
  72.                 registerReceiver(alarmReceiver, filter);  
  73.   
  74.                 Intent intent = new Intent(ALARM_EVENT);  
  75.                 PendingIntent pIntent = PendingIntent.getBroadcast(  
  76.                         this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
  77.                 AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);  
  78.                 alarmMgr.setRepeating(  
  79.                         AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 200, pIntent);  
  80.                 btn_alarm.setText("停止AlarmManager计数");  
  81.             } else {  
  82.                 unregisterReceiver(alarmReceiver);  
  83.                 alarmReceiver = null;  
  84.                 btn_alarm.setText("开始AlarmManager计数");  
  85.             }  
  86.         }  
  87.     }  
  88.   
  89.     private Handler mHandler = new Handler() {  
  90.         @Override  
  91.         public void handleMessage(Message msg) {  
  92.             super.handleMessage(msg);  
  93.             if (msg.what == 0) {  
  94.                 tv_alarm.setText("当前计数值为"+msg.arg1);  
  95.             } else if (msg.what == 1) {  
  96.                 tv_alarm.setText("当前计数值为"+msg.arg1);  
  97.                 btn_counter.setText("CountDownTimer计时结束,重新计时");  
  98.             }  
  99.         }  
  100.     };  
  101.   
  102.     private MyCounter mCounterTask = null;  
  103.     private class MyCounter extends CountDownTimer {  
  104.   
  105.         private int count;  
  106.         public MyCounter(long millisInFuture, long countDownInterval) {  
  107.             super(millisInFuture, countDownInterval);  
  108.             count = 0;  
  109.         }  
  110.   
  111.         @Override  
  112.         public void onTick(long millisUntilFinished) {  
  113.             Message msg = mHandler.obtainMessage();  
  114.             msg.what = 0;  
  115.             msg.arg1 = count++;  
  116.             mHandler.sendMessage(msg);  
  117.         }  
  118.   
  119.         @Override  
  120.         public void onFinish() {  
  121.             Message msg = mHandler.obtainMessage();  
  122.             msg.what = 1;  
  123.             msg.arg1 = count;  
  124.             mHandler.sendMessage(msg);  
  125.         }  
  126.           
  127.     }  
  128.   
  129.     private MyTimerTask mTimerTask = null;  
  130.     private class MyTimerTask extends TimerTask {  
  131.         private int count = 0;  
  132.   
  133.         @Override  
  134.         public void run() {  
  135.             Message msg = mHandler.obtainMessage();  
  136.             msg.what = 0;  
  137.             msg.arg1 = count++;  
  138.             mHandler.sendMessage(msg);  
  139.         }  
  140.     }  
  141.       
  142.     private String ALARM_EVENT = "";  
  143.     private int mCount = 0;  
  144.     private AlarmReceiver alarmReceiver = null;  
  145.       
  146.     public class AlarmReceiver extends BroadcastReceiver {  
  147.   
  148.         @Override  
  149.         public void onReceive(Context context, Intent intent) {  
  150.             if (intent != null) {  
  151.                 tv_alarm.setText("当前计数值为"+mCount++);  
  152.             }  
  153.         }  
  154.     }  
  155.   

转载地址:https://blog.csdn.net/happy_love1990/article/details/77443997 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android HTTP数据格式的解析
下一篇:Android Java的容器类

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年03月14日 17时03分10秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

java数据流转化为图片_输出流读取文件内容转换为图片 2019-04-21
java输入格式_JAVA自学笔记: 利用循环设计当用户输入格式错误的时候重新输入... 2019-04-21
qt界面黑的咋办_关于 Qt设置置顶窗口,透明部分显示黑色底色(已设置透明窗口) 的解决方法... 2019-04-21
tpl怎么搞_emlog后台模板设置功能插件tpl_options 2019-04-21
linux巡检脚本shell,linux系统巡检脚本一枚 2019-04-21
红帽linux如何设置3d桌面,LINUX怎么设置3D桌面? 2019-04-21
linux下的free函数,Linux vmalloc/vfree函数实现解读 2019-04-21
手动搭建Linux云服务器,Linux系统云服务器怎么手动搭建 FTP 服务?四步搞定。 2019-04-21
parrot linux桌面设置,parrot使用一些技巧 2019-04-21
linux 管道统计文件,科学网—[转载]Linux管道命令之文件与文件夹统计 - 高琳琳的博文... 2019-04-21
读文件程序一行的函数c语言,c fgets()函数 读取文件时位置会自动移动下一行吗?该如何处理... 2019-04-21
老船履带工具使用方法_电流表工具的正确使用方法 2019-04-21
中矩阵运算_VS 2017中添加Eigen库-c++矩阵运算工具 2019-04-21
传递list对象作为参数_程序员你如何检查参数的合法性? 2019-04-21
打开stp选择哪个许可证_全省首张“广播电视节目制作经营许可证”电子证照上线“皖事通”... 2019-04-21
互联网和大数据是什么意思_数据化和互联网行业 互联网大数据什么意思 2019-04-21
发那科机器人没有码垛指令_FANUC 机器人码垛编程详细讲解 2019-04-21
python播放器模块_如何在单独的模块中调用播放器 2019-04-21
java吕局部峰值_JVM的运行数据区划分 2019-04-21
时间复杂度为on的排序算法_算法基础--时间复杂度,三个常规O(N?)的排序算法(冒泡、选择、插入)... 2019-04-21