android定时器timer
① Android定时器AlarmManager
AlarmManager是Android的全局定时器。就是在指定时间做一个事情(封装在PendingIntent)。通过PendingIntent的getActivity()、getService()或getBroadcast()来执行。
听起来AlarmManager和Timer很类似,但是Timer有可能因为手机休眠而被杀掉服务,但是AlarmManager可以做到唤醒手机。
注:ALARM_SERVIC是context的一个常量。
以上绝对时间就是手机的时间,相对时间是相对于当前开机时间来说。例如如果是绝对时间,那么你测试可以通过修改系统时间来提前触发。而相对时间的使用场景是强调多久之后触发,例如2小时后,这个时候把时间修改到2小时后也是没用的。
注:以前还有一个POWER_OFF_WAKEUP,即使在关机后还能提醒,但是Android4.0以后就没有了。
该方法用于设置一次性闹钟。第一个参数是闹钟类型,第二个参数是触发时间,第三个参数是动作。
和set一样,但是时间更精准。
重复闹钟,第1、2、4个参数同上,第3个参数是两次闹钟的时间间隔。
和setInexactRepeating一样,但是时间更精准。
以上四个方法时间精不精准的原因还没有深入研究,大概是是否允许系统同时发出多个提醒,意义在于系统唤醒cpu后会把时间接近的alarm同时发出,避免重复唤醒cpu,减少电量。
取消闹钟。
目的:在指定时间从一个发送个广播,收到广播后打印log。界面如下面这样。
布局:
广播接收器:
MainActivity
AndroidManifest要注册一下receiver
经过测试,以上的时间间隔intervalMillis即使设置5秒也是没用的,因为误差(几十秒呢)无法避免,即使是setRepeating。所以精确是相对的。
② android定时器alarmmanager和timer的区别
java的Timer类可以用来计划需要循环执行的任务。
简单的说,一个Timer内部封装装了“一个Thread”和“一个TimerTask队列”,这个队列按照一定的方式将任务排队处理。封装的Thread在Timer的构造方法调用时被启动,这个Thread的run方法按照条件去循环这个TimerTask队列,然后调用TimerTask的run方法。
但是,如果CPU进入了休眠状态,那么这个thread将会因为失去CPU时间片而阻塞,从而造成我们需要的定时任务失效。上述定时任务失效的场景分析:假设定时任务的条件是到了时间xx:yy才能执行,但由于cpu休眠造成线程阻塞的关系,当前系统时间超过了这个时间,即便CPU从终端中恢复了,那么由于条件不满足,定时任务在这一次自然就失效了。
它需要用WakeLock让CPU 保持唤醒状态。这样会大量消耗手机电量,大大减短手机待机时间。这种方式不能满足需求。
AlarmManager是Android 系统封装的用于管理RTC的模块,RTC(Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒CPU。这意味着,如果我们用 AlarmManager 来定时执行任务,CPU 可以正常的休眠,只有在需要运行任务时醒来一段很短的时间。
③ Android 定时器Timer的使用
在我们Android客户端上有时候可能有些任务不是当时就执行,而是过了一个规定的时间在执行此次任务。那么这个时候定时颤慧器的作用就非常有用了。首先开启一个简单的定时器
现在我就相当于定义了拆腔一个定时器,我现在的定时器是向服务器发送Post请求来返回数据刷新到我的界面上那么接下来就是开启定时器了。开启定时器那就非常简单了
开启定时器特别简单基本上一句话就搞定了
开启定时器需要三个参数
1.就是上面所写的你要做的事情 ,上面我写的上向网络发送请求那么这里就时开启定时器请求网络
2.这个参数是你要多长时间后执行这个定时器,这里我写的是0,那么就是0秒后执行我的定时器。
3.这个是最重要的这就是你每次执行时间的间隔 我这里就是说每10秒向网络发送一次请求如果写成1000就是每一秒向网络发送一次请求
如果第三个参数不写的话那么定时器就是几秒后执行 那么定时器只执行一次就不在执行了
其实定时器如果不销毁的话是一直执行的但其实定时器如果一直执行的话那么我们的程序根本就撑不了多长时间就会崩溃所以说定时器用完就要及时的关闭
定时器的开启在写Fragment或者Activity的时候我一般会写在onStart里面
如果销毁的时候会写在onStop里面销毁定时器也非常简单
基本上这一句话就搞定了执行这句话说明是注销定时器
当我们离开本界面的时候就执行这句话那么定时器就不会在执行了当我们进入本界面在onStart执行定时器那么就又开启了定时器所以说这样就写了一个简易版的定时器
一个简单的定时器请求网络就完成了 HttpHolder holder = new HttpHolder(handler); 这是自己写的网络请旅洞衫求类直接调用输入url的服务器地址获得的就是服务器发来的JSON格式的数据
在onStop里面注销定时器那么每次离开本界面的时候那么定时候就销毁了再回到本界面的时候那么就执行onStart里面的开启定时器那么定时器就开启了所以这样就避免了因为定时器开启而使程序崩溃
④ android用timer做定时任务,崩溃的原因
在做定时任务的时候,有的同学可能能会用到Timer这个定时任务的辅助类,
但是使用它会有潜在的风险,风险如下,
(1)时间计算不准确问题
因为Timer是以绝对时间计算定时任务的,会受到系统时间的影响,如果在任务执行期间,更改了系统时间,那么会
导致时间计算不准确问题,导致任务没用按找预定的时间执行。
(2)只能单任务执行
简单讲就是,只能一次执行一个任务,如果前一个任务没有执行完成,后一个任务是无法并行执行的,只能等待前一个任务执行完成
才能执行。也有可能会出现这样的结果,前一个任务执行的时间太长,后几个任务时间短,可能在一个时间段内执行了多个任务,任务又
没有按照我们要执行的时间执行。
(3)非检查异常导致异步任务终止
Timer当在执行的过程中遇到非检查异常的时候,会导致本次任务失败,并且接下来的任务也无法被执行,Timer将会终止执行,这不是
我们要的结果,我们需要一套恢复机制。
Java5以后可以用下面的这个类来替代Time,并且解决了以上三个问题
java.util.concurrent.ScheledThreadPoolExecutor
那么在Android上呢,可以用 java.util.concurrent.ScheledThreadPoolExecutor,也可以用Handler机制做,
但是不建议使用Timer
⑤ android 计时器代码
Timer mTimer = new Timer();
mTask = new TimerTask(){
public void run(){
//execute the task
Message message = new Message();
message.what = DIALOG_HIDE;
//Log.e(TAG, "message.what = DIALOG_HIDE");
mHandler.sendMessage(message);
}
};
mTimer.schele(mTask, 5000);
在主线程里开启timer,等于启动了另一个线程,线程之间的通信是要用handler发送message,然后在主线程里用handler.handleMessage()里面接收并处理。
⑥ android定时器的使用
目前在项目中使用过的定时器主要是两种方式:1.handler的延时任务 2.timer的定时器
下面主要来介绍这两种方式 定时器的用法,和遇到的坑 :
1.handler的延时任务
写了一个demo,是关于hanlder发送延时消息和 取消延时消息的
但是在实际运用的过程中,常常会出现无法移除延时消息的问题,这个问题主要是因为两个runnable的对象不是同一个,
当Activity进入后台运行后再转入前台运行,removeCallbacks无法将updateThread从message queue中移除。这是为什么呢?
在Activity由前台转后台过程中,线程是一直在运行的,但是当Activity转入前台时会重新定义Runnable runnable;也就是说此时从message queue移除的runnable与原先加入message queue中的runnable并非是同一个对象。 解决方式1:如果把runnable定义为静态的则removeCallbacks不会失效,对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,我们做如下修改就能解决上面的这个问题.
解决方式2:将所有的runnable任务放到一个集合中,根据runnable的id移除相应的任务,即可以解决这个问题
2.timer的延时任务
同样用上面的demo来说明使用方法:
要注意的是:
TimerTask运行在一个单独的线程里,而不是UI线程。所以使用 Android timer时,注意android的单线程原则,确保线程安全。不要在TimerTask的run方法中做UI相关的操作,如:TextView.setText()等,这样可能会导致UI线程阻塞。如果需要可以使用handler向UI线程发消息,具体处理由UI线程自己完成。在使用完Timer之后,要使用Timer的cancel方法取消Timer,否则Timer一直在运行。
这里需要注意的是,timer的cancel方法只能执行一次,不能在调用了cancel之后再进行timer的任务执行。
参考文章:
Android 定时器实现的几种方式和removeCallbacks失效问题详解
Android 中Timer和TimeTask完成定时任务