Android源码分析Alarm机制与

前言

本次给大家分析的是Android中Alarm的机制以及它和Binder的交互,所用源码为最新的Android4.4。因为Alarm的功能都是通过Binder来完成的,所以,介绍Alarm之前必须要先介绍下它是如何调用Binder来完成定时功能的。由于内容较多,本文会比较长,在文章结构安排上是这样的:首先简单介绍如何使用Alarm并给出其工作原理,接着分析Alarm和Timer以及Handler在完成定时任务上的差别,然后分析Alarm与Binder的交互,最后分析Alarm机制的源码。

什么是Alarm

Alarm是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(){

Override

publicvoidrun(){

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();

}

}

更多详细介绍,







































北京哪里治疗白癜风比较好
白癜风治疗的好吗



转载请注明:http://www.gslnbdf.com/azyx/1306.html