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三种定时器的示例代码:

import java.util.Timer;
import java.util.TimerTask;import com.example.exmthread.R;import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;public class AlarmActivity extends Activity implements OnClickListener {private TextView tv_alarm;private Button btn_timer;private Button btn_counter;private Button btn_alarm;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_alarm);btn_timer = (Button) findViewById(R.id.btn_timer);btn_counter = (Button) findViewById(R.id.btn_counter);btn_alarm = (Button) findViewById(R.id.btn_alarm);btn_timer.setOnClickListener(this);btn_counter.setOnClickListener(this);btn_alarm.setOnClickListener(this);tv_alarm = (TextView) findViewById(R.id.tv_alarm);ALARM_EVENT = getResources().getString(R.string.alarm_event);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_timer) {if (mTimerTask == null) {mTimerTask = new MyTimerTask();Timer timer = new Timer();timer.schedule(mTimerTask, 50, 200);btn_timer.setText("停止Timer定时计数");} else {mTimerTask.cancel();mTimerTask = null;btn_timer.setText("开始Timer定时计数");}} else if (v.getId() == R.id.btn_counter) {if (mCounterTask == null) {mCounterTask = new MyCounter(8000, 1000);mCounterTask.start();btn_counter.setText("停止CountDownTimer定时计数");} else {mCounterTask.cancel();mCounterTask = null;btn_counter.setText("开始CountDownTimer定时计数");}} else if (v.getId() == R.id.btn_alarm) {if (alarmReceiver == null) {alarmReceiver = new AlarmReceiver();IntentFilter filter = new IntentFilter(ALARM_EVENT);registerReceiver(alarmReceiver, filter);Intent intent = new Intent(ALARM_EVENT);PendingIntent pIntent = PendingIntent.getBroadcast(this, R.string.app_name, intent, PendingIntent.FLAG_UPDATE_CURRENT);AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 200, pIntent);btn_alarm.setText("停止AlarmManager计数");} else {unregisterReceiver(alarmReceiver);alarmReceiver = null;btn_alarm.setText("开始AlarmManager计数");}}}private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == 0) {tv_alarm.setText("当前计数值为"+msg.arg1);} else if (msg.what == 1) {tv_alarm.setText("当前计数值为"+msg.arg1);btn_counter.setText("CountDownTimer计时结束,重新计时");}}};private MyCounter mCounterTask = null;private class MyCounter extends CountDownTimer {private int count;public MyCounter(long millisInFuture, long countDownInterval) {super(millisInFuture, countDownInterval);count = 0;}@Overridepublic void onTick(long millisUntilFinished) {Message msg = mHandler.obtainMessage();msg.what = 0;msg.arg1 = count++;mHandler.sendMessage(msg);}@Overridepublic void onFinish() {Message msg = mHandler.obtainMessage();msg.what = 1;msg.arg1 = count;mHandler.sendMessage(msg);}}private MyTimerTask mTimerTask = null;private class MyTimerTask extends TimerTask {private int count = 0;@Overridepublic void run() {Message msg = mHandler.obtainMessage();msg.what = 0;msg.arg1 = count++;mHandler.sendMessage(msg);}}private String ALARM_EVENT = "";private int mCount = 0;private AlarmReceiver alarmReceiver = null;public class AlarmReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent != null) {tv_alarm.setText("当前计数值为"+mCount++);}}}}

点此查看Android开发笔记的完整目录

Android开发笔记(五十)定时器AlarmManager相关推荐

  1. Android开发笔记(十五)淡入淡出动画TransitionDrawable

    说到淡入淡出动画,可能大家会想到补间动画里面的AlphaAnimation,不过这个深浅动画只能对透明度做渐变效果,也就是只能对一个图形做深浅的颜色变换.如果我们想要从A图片逐渐变为B图片,也就是要实 ...

  2. Android开发笔记(十四)圆弧进度动画CircleAnimation

    一个好看的APP,都有不少精致的动画效果.熟练运用各种动画技术,可让我们的APP灼灼生辉.Android在技术上把动画分为了三类,分别是帧动画FrameAnimation.补间动画TweenAnima ...

  3. Android开发笔记(十九)底部标签栏TabBar

    底部标签页实现思路 现在的APP,大多在页面底部显示标签栏Tabbar,用于切换不同栏目的页面.Tabbar起源于iOS,iOS的Tabbar自动位于页面下方,可是Android搬过来的时候做了改动, ...

  4. Android开发笔记(十八)书籍翻页动画PageAnimation

    前面几节的动画都算简单,本文就介绍一个复杂点的动画--书籍翻页动画.Android有自带的翻页动画ViewPager,不过ViewPager只实现了平移效果.即便使用补间组合动画或者属性动画,也只是把 ...

  5. Android开发笔记(十六)秋千摇摆动画SwingAnimation

    上节博主介绍了AlphaAnimation和淡入淡出动画的使用,其实AlphaAnimation只是四种补间动画中的一种.那么为了加深对其他补间动画的理解,我想说说旋转动画RotateAnimatio ...

  6. Android开发笔记(十二)测量尺寸与下拉刷新

    尺寸测量的配置 控件宽和高的设置方式 大家知道,自定义视图的目的就是要在屏幕上显示期望的图案,那在绘制图案之前,我们得先知道这个图案的尺寸(如宽多少高多少). 一般在xml中给控件的宽和高有三种赋值方 ...

  7. Android开发笔记(十)常用的图片加工操作

    APP开发自然少不了各种图片的加工处理,虽然说加工图片是美工干的活,但是码农会些简单的操作总归是好事.一些简单的加工如缩放.旋转.裁剪.格式转换,使用ACDSee就够用了,不过有些稍微复杂的操作得借助 ...

  8. android开发标签栏应该设置多少,Android开发笔记(十九)底部标签栏TabBar

    底部标签页实现思路 现在的APP,大多在页面底部显示标签栏Tabbar,用于切换不同栏目的页面.Tabbar起源于iOS,iOS的Tabbar自动位于页面下方,可是Android搬过来的时候做了改动, ...

  9. Android开发笔记(一百一十五)设计工具

    UI/UE UI是User Interface的简称,即用户接口,也称用户界面.UI泛指用户的操作界面,对手机来说,UI设计就是app的页面设计.一个好的UI,不但能让用户操作起来更加舒适.方便,而且 ...

  10. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

最新文章

  1. ccf压缩编码java_压缩编码(CCF)——动态规划
  2. 《算法竞赛进阶指南》打卡-基本算法-AcWing 94. 递归实现排列型枚举:dfs、二进制状态压缩
  3. Hibernate持久化对象三种状态
  4. JavaScript返回上一页代码区别
  5. dcloud会员激活mui
  6. hdu 1698 Just a Hook(线段树区间修改)
  7. mc穿越时空地图android,《我的世界1.8X》穿越时空地图存档
  8. java在Intellij上使用sigar
  9. GitHub 优秀的 Android 开源项目
  10. 大数据算法_大数据挖掘十大经典算法
  11. 【数据结构】——逆波兰表达式
  12. 分数加减法(C语言)
  13. QT-数据可视化大屏1
  14. XP系统无法访问\\192.168.1.104无法访问。你可能没有权限使用网络资源。与这台服务器的管理员联系以查明你是否有访问权限
  15. 网站自动SEO优化软件
  16. p=p-next 表达了什么意思
  17. heu oj 1011 square
  18. “全民创业”是新时代的上山下乡
  19. 小白记录第一个Android APP,VS2019,Xamarin,C#
  20. winxpnbsp;sp3

热门文章

  1. 吴恩达机器学习【第四天】多元线性规划模型
  2. 关于利用np.contour画出logistic模型决策边界(plot_decision_regions)的一点感想
  3. 861. Score After Flipping Matrix
  4. css设计引言,HTML5与CSS3设计模式 引言(3)
  5. Memcached安装与使用实例
  6. 小米6android版本更新,小米6正式迎来了安卓9.0稳定版升级,一代神机继续创造辉煌...
  7. redis 是哪个厂家的_redis 基本数据类型-字符串(String)
  8. python 图形_Python切分图像小案例(1、3、2、4象限子图互换)
  9. android 启动多个进程,Android开启多进程
  10. php与tp5,PHP开发(33)-ThinkPHP5.0(5)命名空间与TP5-PhpStorm