Android Alarm:要点解析

1、什么是Alarm?

简单来说可以理解成为闹钟,根本来说,是在某一个时间点,通过PendingIntent唤起某一个APP,执行指定的操作;


2、Alarm有哪几种?

根据“时间纬度”+“CPU唤起纬度”进行排列组合,因此一共有4种;

时间纬度:绝对时间(常规的年月日)  or  相对时间(相对于开机之后,例如开机10分钟)

CPU唤起: 唤起 OR 不唤起

绝对时间+ 唤起CPU=AlarmManager.RTC_WAKEUP

绝对时间+不唤起CPU=AlarmManager.RTC

相对时间+ 唤起CPU=AlarmManager.ELAPSED_REALTIME_WAKEUP

相对时间+不唤起CPU=AlarmManager.ELAPSED_REALTIME


3、如何设置Alarm?

//1、创建intent
Intent intent = new Intent(ALARM_TEST);
//2.创建pendingIntent
PendingIntent pendingIntent =   PendingIntent.getBroadcast(mContext,0,intent,PendingIntent.FLAG_ONE_SHOT);
//3.获取系统AlarmManager
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(ALARM_SERVICE);
//4-1 使用set创建Alarm
alarmManager.set(AlarmManager.RTC,DateTool.nowInMs() ,pendingIntent);
//4-2 使用setRepeating创建Alarm
alarmManager.setRepeating(AlarmManager.RTC,DateTool.nowInMs(), 1000 ,pendingIntent);
//4-3 使用setInexactRepeating创建Alarm
alarmManager.setInexactRepeating(AlarmManager.RTC,DateTool.nowInMs(), 1000,pendingIntent);

3-1、AlarmManager中set、setRepeating、setInexactRepeating之间的差别

(1) AlarmManager.set: 一次性Alarm,在指定时间触发操作,需要指定其触发时间(triggerAtTime);

(2)AlarmManager.setRepeating:重复性Alarm,在指定时间触发操作,需要指定其触发时间(triggerAtTime),并且指明重复周期(interval);

(3)AlarmManager,setInexactRepeating:重复性Alarm,与setRepeating的区别是,存在一个优化逻辑;如果你的Alarm是RTC_WAKEUP or RTC类型,并且你的唤起周期(interval)是15分钟的整数倍,那么你的alarm首次执行执行时间并不一定是你设置的触发时间,系统会计算一个偏差,使其跟其他Alarm对齐,目的是尽可能的减少系统唤起次数,起到优化性能的作用;


4、Alarm系统是如何实现的?

所有Alarm实现都是在AlarmManagerService中;


4-1:Alarm存储:

分别使用4个List在内存中存储4种对应类型的Alarm信息,并且每一个List都是按照时间先后顺序排列的;

private final ArrayList
    
    
     
      mRtcWakeupAlarms = new ArrayList
     
     
      
      ();
    private final ArrayList
      
      
       
        mRtcAlarms = new ArrayList
       
       
        
        ();
    private final ArrayList
        
        
          mElapsedRealtimeWakeupAlarms = new ArrayList 
         
           (); private final ArrayList 
          
            mElapsedRealtimeAlarms = new ArrayList 
           
             (); 
            
           
          
        
       
       
      
      
     
     
    
    

4-2:Alarm新增:

根据APP申明的Alarm类型,找到指定的List,根据唤起时间的先后顺序,插入到该List中;并且,通知内核,在该alarm需要唤起的时候,唤起AlarmThread

 public void setRepeating(int type, long triggerAtTime, long interval, 
            PendingIntent operation) {
        if (operation == null) {
            Slog.w(TAG, "set/setRepeating ignored because there is no intent");
            return;
        }
        synchronized (mLock) {
        		//1、创建Alarm
            Alarm alarm = new Alarm();
            alarm.type = type;
            alarm.when = triggerAtTime;
            alarm.repeatInterval = interval;
            alarm.operation = operation;
            
            //2、判断是否存在相同Alarm,是的话,移除它
            removeLocked(operation);

            if (localLOGV) Slog.v(TAG, "set: " + alarm);
						//3. 保存Alarm到list中
            int index = addAlarmLocked(alarm);
            if (index == 0) {
            //4、通知内核,新增Alarm
                setLocked(alarm);
            }
        }
    }

4-3:Alarm执行:
(1)定义一个名为AlarmThread的Thread,为一个while(true)实现的线程,等待内部唤起;

(2)唤起AlarmThread后,遍历4个List,搜索符合条件的Alarm,条件为:Alarm执行时间小于当前时间;

(3)在搜索Alarm过程中,如果Alarm符合条件,并且需要重复唤起该Alarm,计算该Alarm下次执行的时间,重新加入对应Alarm List;

(5)依次调用符合条件的Alarm中PendingIntent的send方法;

(6)凡是所有符合条件的Alarm中,存在一个唤起CPU的Alarm,那么CPU将会被唤起,直到所有Alarm的PendingIntent.send调用完毕;


5、注册两个PendingIntent完全相同,但是首次执行时间跟周期不同的Alarm,会怎么样?

在新增Alarm时,凡是检测到有PendingIntent完全相同的Alarm,一律之前设定的Alarm删除,依最后一次设定的Alarm为准;


6、注册一个Alarm,设置其执行时间在过去,那么它还会执行么?

(1)增加Alarm记录到相应的List中;

(2)唤起AlarmThread;

结果就是:立刻执行


6、移除一个APP,它设置的Alarm会怎么样?

改App设置的所有Alarm,都会被删除;


7、更新一个APP,它设置的Alarm会怎么样?

不做任何影响,被系统保留;


8、修改本机时间,已经设置的Alarm会怎么样?

AlarmThread会被唤起,然后所有符合条件的Alarm会被执行,并且Alarm下次执行的时间会成为:当前时间+该Alarm周期


9、重启手机,已经注册的Alarm会怎么样,下次启动还能用么?

由于Alarm是存储在内存中,并没有做持久化操作,因此重启后,所有注册的Alarm一律失效;



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值