本次给大家分析的是Android中Alarm的机制以及它和Binder的交互,所用源码为最新的Android4.4。因为Alarm的功能都是通过Binder来完成的,所以,介绍Alarm之前必须要先介绍下它是如何调用Binder来完成定时功能的。由于内容较多,本文会比较长,在文章结构安排上是这样的:首先简单介绍如何使用Alarm并给出其工作原理,接着分析Alarm和Timer以及Handler在完成定时任务上的差别,然后分析Alarm与Binder的交互,最后分析Alarm机制的源码。
什么是AlarmAlarm是android提供的用于完成闹钟式定时任务的类,系统通过AlarmManager来管理所有的Alarm,Alarm支持一次性定时任务和循环定时任务,
Alarm和Timer以及Handler在定时任务上的区别相同点:
三者都可以完成定时任务,都支持一次性定时和循环定时(注:Handler可以间接支持循环定时任务)
不同点:
Handler和Timer在定时上是类似的,二者在系统休眠的情况下无法正常工作,定时任务不会按时触发。Alarm在系统休眠的情况下可以正常工作,并且还可以决定是否唤醒系统,同时Alarm在自身不启动的情况下仍能正常收到定时任务提醒,但是当系统重启或者应用被杀死的情况下,Alarm定时任务会被取消。另外,从Android4.4开始,Alarm事件默认采用非精准方式,即定时任务可能会有小范围的提前或延后,当然我们可以强制采用精准方式,而在此之前,Alarm事件都是精准方式。
Alarm与Binder的交互Alarm由AlarmManager来管理,从使用方式来看,AlarmManager很简单,我们只要得到了AlarmManager的对象,就可以调用set方法来设定定时任务了,而如何得到AlarmManager对象呢?也很简单,AlarmManageralarmMgr=(AlarmManager)getSystemService(Context.ALARM_SERVICE);下面我们去看看AlarmManager的set方法,当然AlarmManager还有setRepeating方法,但是二者是类似的。
可见这个Stub类就是一个普通的Binder,只不过它实现了IAlarmManager接口。它还有一个静态方法asInterface,这个方法很有用,通过它,我们就可以将IBinder对象转换成IAlarmManager的实例,进而通过实例来调用其方法。什么是Binder?这个还真不好说,但是我们要知道Binder在Android系统中有大量的应用,大部分Manager都通过Binder来实现(包括AlarmManager),而Service和AIDL也是通过Binder来实现调用的。至于Binder和IBinder的关系,很简单,就是Binder实现了IBinder接口。由于AlarmManagerService继承了IAlarmManager.Stub,所以AlarmManagerService也相当于实现了IAlarmManager接口,所以很显然,AlarmManagerService就是AlarmManager中用于和其交互的mService。不过,还没有完,因为上面的结论不是我瞎猜的,是有代码层面的依据的,下面我将带领大家一起去探索寻找mService的过程,通过这个过程,我们会对Binder机制有更加深刻的认识。
各种Manager和Binder服务的对应关系首先Dalvik虚拟机会在SystemServer中创建一个叫做ServerThread的线程并调用它的initAndLoop方法,在initAndLoop方法中会创建主线程Looper和初始化各种Manager所对应的Binder服务,我们所常见的Binder服务如WindowManagerService、AlarmManagerService、PowerManagerService等均在这里创建并加入到ServiceManager中进行统一管理。而我们通过getSystemService方式来得到各种Manager的工作主要是在ContextImpl中完成的,不过LayoutInflater、WindowManager以及SearchManager除外。通过ContextImpl我们可以知道各种Manager和Binder服务的一一对应关系,比如AlarmManager对应AlarmManagerService、WindowManager对应WindowManagerService。
上面只是结论,为了真正搞清楚各种Manager所对应的Binder服务,下面将要看一系列代码,首先看SystemServer的代码:
code:SystemServer
publicclassSystemServer{
privatestaticfinalStringTAG=SystemServer;
publicstaticfinalintFACTORY_TEST_OFF=0;
publicstaticfinalintFACTORY_TEST_LOW_LEVEL=1;
publicstaticfinalintFACTORY_TEST_HIGH_LEVEL=2;
staticTimertimer;
staticfinallongSNAPSHOT_INTERVAL=60*60*;//1hr
//Theearliestsupportedtime.Wepickonedayinto,to
//giveanytimezonecoderoomwithoutgoingintonegativetime.
privatestaticfinallongEARLIEST_SUPPORTED_TIME=*;
/**
*Calledtoinitializenativesystemservices.
*初始化本地系统服务,jni方法
*/
privatestaticnativevoidnativeInit();
//main方法,由底层调用
publicstaticvoidmain(String[]args){
if(System.currentTimeMillis()EARLIEST_SUPPORTED_TIME){
//Ifadevicesclockisbefore(before0),alotof
//APIscrashdealingwithnegativenumbers,notably
//java.io.File#setLastModified,soinsteadwefakeitand
//hopethattimefromcelltowersorNTPfixesit
//shortly.
Slog.w(TAG,Systemclockisbefore;settingto.);
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
if(SamplingProfilerIntegration.isEnabled()){
SamplingProfilerIntegration.start();
timer=newTimer();
timer.schedule(newTimerTask(){
Overridepublicvoidrun(){
SamplingProfilerIntegration.writeSnapshot(system_server,null);
}
},SNAPSHOT_INTERVAL,SNAPSHOT_INTERVAL);
}
//Mmmmmm...morememory!
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
//Thesystemserverhastorunallofthetime,soitneedstobe
//asefficientaspossiblewithitsmemoryusage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
Environment.setUserRequired(true);
System.loadLibrary(android_servers);
Slog.i(TAG,EnteredtheAndroidsystemserver!);
//初始化本地服务.
nativeInit();
//这里是关键,ServerThread被创建,同时其initAndLoop被调用
ServerThreadthr=newServerThread();
thr.initAndLoop();
}
}
更多详细介绍,北京哪里治疗白癜风比较好白癜风治疗的好吗