Android开发笔记(五十)定时器AlarmManager
2016-01-15 17:36
519 查看
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发送消息来间接实现。
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和AlarmManager的示例代码:
import java.util.Timer; import java.util.TimerTask; 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.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_alarm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_alarm); btn_timer = (Button) findViewById(R.id.btn_timer); btn_alarm = (Button) findViewById(R.id.btn_alarm); btn_timer.setOnClickListener(this); btn_alarm.setOnClickListener(this); tv_alarm = (TextView) findViewById(R.id.tv_alarm); ALARM_EVENT = getResources().getString(R.string.alarm_event); } @Override public 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_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() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); tv_alarm.setText("当前计数值为"+msg.arg1); } }; private MyTimerTask mTimerTask = null; private class MyTimerTask extends TimerTask { private int count = 0; @Override public void run() { Message msg = mHandler.obtainMessage(); msg.arg1 = count++; mHandler.sendMessage(msg); } } private String ALARM_EVENT = ""; private int mCount = 0; private AlarmReceiver alarmReceiver = null; public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { tv_alarm.setText("当前计数值为"+mCount++); } } } }
点此查看Android开发笔记的完整目录
相关文章推荐
- Android_GreenDao傻瓜式入门
- Android中的同步机制
- Android Studio——位图BitMap
- 第2部分 创建第一个Android程序
- Android-PullToRefresh库中的PullToRefreshListView添加header
- Android Studio中关于getter和setter的生成
- Android——按钮操作
- Android Studio安装插件
- 实例解析Android ImageView的scaleType属性
- 王立平--android中的anim(动画)
- 详解Android MVP开发模式
- Android 讲解:广播
- Android程序开发之动态设置ImageView的亮度
- 自动生成Android屏幕适配的dimens.xml文件工具类
- Android 获取手机图片保存的一个通用工具类
- Android Library Project工程导出jar包供其它工程使用
- Android内存泄露分析之StrictMode
- Intellij IDEA + Android SDK + Genymotion Emulator打造最佳Android开发环境
- 多方法批量删除Android中无用的资源(更新Android Studio2.1工具)
- Ubuntu搭建Android源码编译环境