• Android定时相关


    执行定时任务的方法:

    1、使用Timer

    package com.hjqjl.whdemo.feature.feature0.ui.activity;
    
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    
    import com.blankj.utilcode.util.ToastUtils;
    import com.hjqjl.whdemo.R;
    import com.hjqjl.whdemo.base.BaseActivity;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TimerActivity extends BaseActivity {
        public static void start(Context context) {
            Intent starter = new Intent(context, TimerActivity.class);
            context.startActivity(starter);
        }
    
        private Timer timer;
        private TimerTask task;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_timer);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            startTimer();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            stopTimer();
        }
    
        /**
         * 启动定时器
         */
        public void startTimer() {
            if (timer == null) {
                timer = new Timer();
            }
            if (task != null) {
                task.cancel();
            }
            task = new TimerTask() {
                @Override
                public void run() {
                    //执行定时任务
                    ToastUtils.showShort("执行定时任务Timer");
                }
            };
            if (timer != null) {
                timer.schedule(task, 3000, 60000);
            }
        }
    
        /**
         * 停止定时器 刷新上传数据
         */
        private void stopTimer() {
            if (timer != null) {
                task.cancel();
                timer.cancel();
                timer.purge();
                timer = null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    2、使用ScheduledExecutorService

    package com.hjqjl.whdemo.feature.feature0.ui.activity;
    
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    
    import com.blankj.utilcode.util.ToastUtils;
    import com.hjqjl.whdemo.R;
    import com.hjqjl.whdemo.base.BaseActivity;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class TimerActivity extends BaseActivity {
        public static void start(Context context) {
            Intent starter = new Intent(context, TimerActivity.class);
            context.startActivity(starter);
        }
    
        private ScheduledExecutorService exec;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_timer);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            initTimer();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            endExecutorScan();
        }
    
        private boolean isTimerRun = true;
    
        private void initTimer() {
            endExecutorScan();
            exec = Executors.newSingleThreadScheduledExecutor();//启动定时线程池
            if (exec != null) {
                exec.scheduleWithFixedDelay(new Runnable() {
                                                @Override
                                                public void run() {
                                                    if (isTimerRun) {
                                                        //执行定时任务
                                                        ToastUtils.showShort("执行定时任务ScheduledExecutorService");
                                                    }
                                                }
                                            },
                        3, 60, TimeUnit.SECONDS);
            }
        }
    
        private void endExecutorScan() {
            if (exec != null) {
                isTimerRun = false;
                exec.shutdownNow();
            }
            exec = null;//非单例模式,置空防止重复的任务
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    3、倒计时按钮

    实现如发送短信验证码等功能,通常需要倒计时功能,防止用户频繁按按钮发送短信。
    效果如下:
    在这里插入图片描述

    import android.os.CountDownTimer;
    import android.widget.Button;
    
    /**
     * 倒计时Button帮助类
     * 用法
     * CountDownButtonHelper countDownButtonHelper = new CountDownButtonHelper(smsBtn);
     * countDownButtonHelper.start();//开始
     * ----------------
     * countDownButtonHelper.cancel();//取消
     */
    public class CountDownButtonHelper {
        // 倒计时timer
        private CountDownTimer countDownTimer;
        // 计时结束的回调接口
        private OnFinishListener listener;
    
        private Button mButton;
        private String btnText;
    
        /**
         * @param button 需要显示倒计时的Button
         */
        public CountDownButtonHelper(Button button) {
            this.mButton = button;
            // 由于CountDownTimer并不是准确计时,在onTick方法调用的时候,time会有1-10ms左右的误差,这会导致最后一秒不会调用onTick()
            // 因此,设置间隔的时候,默认减去了10ms,从而减去误差。
            // 经过以上的微调,最后一秒的显示时间会由于10ms延迟的积累,导致显示时间比1s长max*10ms的时间,其他时间的显示正常,总时间正常
            countDownTimer = new CountDownTimer(10 * 1000, 1 * 1000 - 10) {//倒计时的最大值10s;倒计时的间隔1s
    
                @Override
                public void onTick(long time) {
                    // 第一次调用会有1-10ms的误差,因此需要+15ms,防止第一个数不显示,第二个数显示2s
                    mButton.setText("(" + ((time + 15) / 1000) + "秒)");
                    //Logger.d("time = " + (time) + " text = " + ((time + 15) / 1000));
                }
    
                @Override
                public void onFinish() {
                    mButton.setEnabled(true);
                    if (btnText == null) {
                        mButton.setText("验证码");
                    } else {
                        mButton.setText(btnText);//设置button上的文字
                    }
                    if (listener != null) {
                        listener.finish();
                    }
                }
            };
        }
    
        /**
         * 开始倒计时
         */
        public void start() {
            mButton.setEnabled(false);
            countDownTimer.start();
        }
    
        /**
         * 关闭倒计时,一般onDestroy里会用到
         */
        public void cancel() {
            if (countDownTimer != null) {
                countDownTimer.cancel();
            }
        }
    
        /**
         * 设置倒计时结束的监听器
         *
         * @param listener
         */
        public void setOnFinishListener(OnFinishListener listener) {
            this.listener = listener;
        }
    
        /**
         * 计时结束的回调接口(外部要调用所以用public)
         */
        public interface OnFinishListener {
            void finish();
        }
    
        /**
         * 设置按钮里的文字
         */
        public void setBtnText(String btnText) {
            this.btnText = btnText;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    在activity中的实现方法参考如下:

    import android.content.Context;
    import android.content.Intent;
    import android.view.View;
    
    import com.hjqjl.whdemo.databinding.ActivityCountDownBinding;
    import com.hjqjl.whdemo.utils.CountDownButtonHelper;
    import com.hjqjl.whdemo.utils.ToastUtils;
    
    /**
     * 倒计时按钮
     */
    public class CountDownActivity extends BaseActivity {
        public static void actionStart(Context context) {
            Intent intent = new Intent(context, CountDownActivity.class);
            context.startActivity(intent);
        }
    
        private CountDownButtonHelper countDownButtonHelper;
        private ActivityCountDownBinding binding;
    
        @Override
        protected void initData() {
            binding = ActivityCountDownBinding.inflate(getLayoutInflater());
            View view = binding.getRoot();
            setContentView(view);
    
            countDownButtonHelper = new CountDownButtonHelper(binding.btnCountDown);
        }
    
        @Override
        protected void processLogic() {
            binding.btnCountDown.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    countDownButtonHelper.start();
                }
            });
            countDownButtonHelper.setOnFinishListener(new CountDownButtonHelper.OnFinishListener() {
                @Override
                public void finish() {
                    ToastUtils.showToast(mContext, "倒计时结束调用");
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            if (null != countDownButtonHelper) {
                countDownButtonHelper.cancel();
            }
            super.onDestroy();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    4、利用AlarmManager定时执行任务

    需要用到广播

    package com.apep.fivefive.utils;
    
    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.Context;
    import android.content.Intent;
    
    import com.apep.fivefive.receiver.ReLaunchAppReceiver;
    import com.blankj.utilcode.util.LogUtils;
    import com.blankj.utilcode.util.TimeUtils;
    import com.blankj.utilcode.util.ToastUtils;
    
    import java.util.Calendar;
    import java.util.Random;
    import java.util.TimeZone;
    
    /**
     * 2021/7/8 17:05 wh
     */
    public class ReLaunchAppUtils {
        public static void reLaunchApp(Context context, String msg) {
            ToastUtils.make().setTextSize(50).setDurationIsLong(true).show("" + msg);
            Intent intent = new Intent(context, ReLaunchAppReceiver.class);
            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
            //得到AlarmManager实例
            AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            am.set(AlarmManager.RTC, System.currentTimeMillis() + (1000 * 10), pi);//定时10s之后
        }
    
        /**
         * 凌晨一定时间内重启
         *
         * @param context 上下文
         */
        public static void reLaunchApp2(Context context) {
            //得到日历实例,主要是为了下面的获取时间
            Calendar mCalendar = Calendar.getInstance();
            mCalendar.setTimeInMillis(System.currentTimeMillis());
    
            // 这里时区需要设置一下,不然可能个别手机会有8个小时的时间差
            mCalendar.setTimeZone(TimeZone.getTimeZone("GMT+8"));
            //是设置日历的时间,主要是让日历的年月日和当前同步
            mCalendar.setTimeInMillis(System.currentTimeMillis());
            //设置在几点提醒  设置的为点
            int randomH = new Random().nextInt(4);
            mCalendar.set(Calendar.HOUR_OF_DAY, randomH);
            //设置在几分提醒  设置的为0分
            int randomM = new Random().nextInt(60);
            mCalendar.set(Calendar.MINUTE, randomM);
            //下面这两个看字面意思也知道
            int randomS = new Random().nextInt(60);
            mCalendar.set(Calendar.SECOND, randomS);
            //设置下一天
            mCalendar.add(Calendar.DAY_OF_MONTH, 1);
    
    //        ToastUtils.make().setTextSize(50).setDurationIsLong(true).show("" + msg);
    		ReLaunchAppReceiver.class为广播接受者
            Intent intent = new Intent(context, ReLaunchAppReceiver.class);
            PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
            //得到AlarmManager实例
            AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            LogUtils.v(TimeUtils.millis2String(mCalendar.getTimeInMillis()));
             //**********注意!!下面的三个根据实际需求任选其一即可*********
    
            /*
             * 单次提醒 
             * RTC_WAKEUP 在设备关闭时唤醒设备。
             * RTC 此警报不会唤醒设备;如果它在设备睡眠时关闭,则直到设备下次醒来时才会发送。
             * mCalendar.getTimeInMillis() 上面设置的11点0分的时间点毫秒值
             */
            am.set(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pi);
    
            /*
             * 重复提醒
             * 第一个参数是警报类型;下面有介绍
             * 第二个参数网上说法不一,很多都是说的是延迟多少毫秒执行这个闹钟,但是我用的刷了MIUI的三星手机的实际效果是与单次提醒的参数一样,即设置的13点25分的时间点毫秒值
             * 第三个参数是重复周期,也就是下次提醒的间隔 毫秒值 我这里是一天后提醒
             */
    //        am.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), (1000 * 60 * 60 * 24), pi);
    
            /*
             * 时间要求比set精准(耗能大)
             */
    //        am.setExact(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(), pi);
        }
        
    	/**
    	  * 关闭定时
    	  */
    	 private void stopRemind(Context context){
    	     Intent intent = new Intent(context, ReLaunchAppReceiver .class);
    	     PendingIntent pi = PendingIntent.getBroadcast(context, 0,
    	             intent, 0);
    	     AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
    	     //取消警报
    	     am.cancel(pi);
    	     Toast.makeText(this, "关闭了提醒", Toast.LENGTH_SHORT).show();
    	 }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    广播ReLaunchAppReceiver 不要忘记在AndroidManifest.xml中配置

    public class ReLaunchAppReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            //当系统到我们设定的时间点的时候会发送广播,执行这里
            LogUtils.e("ReLaunchReceiver");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    C#,怎么修改(VS)Visual Studio 2022支持的C#版本
    equals提高执行速度/性能优化
    智能运维应用之道,告别企业数字化转型危机
    【excel技巧】如何取消excel隐藏?
    Mean Squared Error 和 Maximum-A-Posterior (Maximum Likelihood Estimation) 的关系
    【Python零基础入门篇 · 5】:if判断的用法、内置函数range()、for循环和while循环以及break和contine
    时空预测 | 线性时空预测模型、图时空预测
    11 Python的正则表达式
    WebDAV之π-Disk派盘 + 小书匠
    [MRCTF2020]套娃-1
  • 原文地址:https://blog.csdn.net/hjqjl/article/details/127726592