时代会为你做出选择,不管你是否愿意。
最近的移动端的工作似乎也是到了瓶颈,工作并没有像15-16年那么火爆,貌似市场上出现供过于求的状态,但是没有必要感觉不安,你有着逻辑基础,有着基础能力,闭关几月在去精通一门技术又何妨?
如果你想要飞,就拼力让自己的羽翼丰满,翅膀坚硬,而不只是拥有梦想?
实际上,在开发的过程中,我们经常遇到的情景接收短信验证码?
这时候你可以开启一个线程自己书写逻辑,也可以使用android的创建定时任务功能。
android定时任务有两种:
1:Timer类。
2:Alarm机制。
现在具体说说:
Timer:Timer的使用必须和TimerTask结合在一起,如果不太明白可以百度搜索一下使用方法。
CountDownTimer:表示倒计时任务类,很适合实际开发中的接收验证码倒计时使用。下面就是这个类的使用:因为你CountDownTimer是抽象类,所以必须实现里面的抽象方法
class MyTimer extends CountDownTimer{/*** millisInFuture:总时长* countDownInterval:间隔时长*/ public MyTimer(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); }/*** millisUntilFinished 每次执行倒计时一次该方法就会被触发,并返回剩余时长*/ @Override public void onTick(long millisUntilFinished) { }/*** 倒计时执行完成的时候触发的动作*/ @Override public void onFinish() { } }Alarm机制:
在网上搜索最多的还是Timer的使用,对于Alarm机制的讲解并不多,但是这里整理一下:
先看一段代码:创建一个10s的定时任务
AlarmManager manager = ((AlarmManager) getSystemService(ALARM_SERVICE)); int time = 10*1000; long triggerAtTime = SystemClock.elapsedRealtime()+time; Intent i = new Intent(this,AlarmService.class); PendingIntent pendingIntent = PendingIntent.getService(this,0,i,0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);上面的代码就是 创建定时任务,但是看着有些蒙,下面说说:
1.创建Alarm定时任务,首先需要AlarmManager对象:
AlarmManager manager = ((AlarmManager) getSystemService(ALARM_SERVICE));2.调用AlarmManager.set()的方法就可以设置定时任务。
set(int type, long triggerAtMillis, PendingIntent Operation)看看set()方法中的三个参数的意义:
type:指定AlarmManager的工作类型,有一下4中可选:

解释:
ELAPSED_REALTIME_WAKEUP:定时任务的触发时间从系统开机的时刻开始算起,同时唤醒CPU。
ELAPSED_REALTIME:也是触发时间从系统开机的时刻算起,但是不会唤醒CPU
RTC_WAKEUP:定时任务触发时间从1970年1月1日0点开始算起,同时唤醒CPU
RTC:定时任务触发时间从1970年1月1日0点开始算起,但是不会唤醒CPU
所以对于指定方式的不同,会直接影响第二个参数的计算方式:
triggerAtMillis:如果type的取值为ELAPSED_REALTIME_WAKEUP或者ELAPSED_REALTIME的时候,那么时间使用
获取开机至今所经历的毫秒数
如果type的取值为RTC_WAKEUP或者RTC_WAKEU的时候,那么时间使用
获取1970年1月1日0时至今的时间
operation:是一个PendingIntent广播中有提到的,当到达触发时间时,会自动执行PendingIntenet中的逻辑内容。
那我们现在看看上述的代码,是否能明白写呢?上述代码的意义是 以开机时间为参考,10s之后执行AlarmService的内容。
实践操作:
需求:每隔10s开启一个service的服务操作
创建AlarmService如下:
public class AlarmService extends Service { int i = 0; AlarmManager manager; PendingIntent pendingIntent; PRivate static final String TAG = "AlarmService"; public AlarmService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this,"启动服务",Toast.LENGTH_SHORT).show(); Log.i(TAG, "onStartCommand: i------>"+i++); manager = ((AlarmManager) getSystemService(ALARM_SERVICE)); int time = 10*1000; long triggerAtTime = SystemClock.elapsedRealtime()+time; Intent i = new Intent(this,AlarmService.class); pendingIntent = PendingIntent.getService(this,0,i,0); manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy: AlarmManager is cancle"); manager.cancel(pendingIntent); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); }}然后创建Actvity中的按钮来启动服务和结束服务就好了,但是结束服务之后一定要将alarm进行取消,不然时间一到,Alarm还是会执行服务的启动的。
public class AlarmActivity extends AppCompatActivity { Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_alarm); intent = new Intent(AlarmActivity.this,AlarmService.class); findViewById(R.id.btn_Alarm).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startService(intent); } }); findViewById(R.id.btn_Alarm_stop).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); }}我们看一下结果

每隔10s都会尽心一次提示以及输出。
点击取消按钮:

再看,关闭服务之后在不会进行输出,所以成功了。
当然目前的功能还是比较单一,在实际的开发中你可能要用服务进行网络请求,进行返回数据的判断等等。
注意:从android4.4开始,Alarm任务的触发时间将会变得不精准,有可能会拖延一段时间后任务才回得到执行,但这并不是bug。
而是系统在耗电性方面做得优化,系统会自动检测目前有多少Alarm任务存在,然后将触发时间相近的的几个任务放在一起进行执行,这样可以大幅度的减少CPU被唤醒的次数,从而延长电池的使用寿命。
当然,如果要求是时间准确无误,就使用setExact()方法代替set()方法就好。
Doze模式
在android6.0的系统中,google加入Doze模式,目的是延长电池的寿命,如果设备未插电源且屏幕关闭了一段时间后就会进入Doze模式。在Doze模式下系统会对CPU。网络,以及Alarm等活动进行限制,从而延长电池寿命。
具体看看Doze模式下受限的功能:
网络访问被禁止 系统忽略唤醒CPU或者屏幕操作 系统不再执行wifi扫描 系统不再提供同步服务‘ Alarm任务将会在下次退出Doze模式的时候执行
对于Alarm来讲,在Doze模式下,我们的Alarm任务将会变得不准时。当然,大多数情况这是可以理解的,因为只有长时间不适用手机的时候才会进入Doze模式,但是关于这个长时间是多长没有具体的说明。
当然如果你有特殊的要求,要求Alarm在Doze模式下也可以正常执行,调用AlarmMananger的setAndAllowWhileIdle()或setExactAndAllowWhileIdle()方法就可以让程序在Doze模式下也可以正常的执行,区别和set()与setExact()方法一致
新闻热点
疑难解答