当前位置:首页 » 安卓系统 » android定时任务的

android定时任务的

发布时间: 2023-01-14 09:14:52

⑴ android怎么设置一个定时的任务

我知道的有三种方法;
方法一:可以通过android自带的Handler机制,里面有new Handler().postDelayed(new Runnable(){
@Override
public void run() {
//延迟的时间到了执行
}
},延迟的时间);

方法二:可以通过java里面的线程来写,new Thread().sleep(延迟时间);时间到了会继续执行;
方法三:java定时器(有很多方法)例如:
Timer timer = new Timer();
timer.schele(new TimerTask() {
public void run() {
System.out.println("-------设定要指定任务--------");
}
}, long delay,long period);
delay延迟的时间,period为多久执行一次;
个人推荐用方法一,毕竟安卓系统自带的,并且安卓不适合加定时器,如果处理不当一直执行的话,要么卡,要么程序崩溃。还有发布版本可能审核不通过。

⑵ android定时器的使用

  目前在项目中使用过的定时器主要是两种方式:1.handler的延时任务 2.timer的定时器

  下面主要来介绍这两种方式 定时器的用法,和遇到的坑 :
  1.handler的延时任务
  写了一个demo,是关于hanlder发送延时消息和 取消延时消息的

  但是在实际运用的过程中,常常会出现无法移除延时消息的问题,这个问题主要是因为两个runnable的对象不是同一个,
  当Activity进入后台运行后再转入前台运行,removeCallbacks无法将updateThread从message queue中移除。这是为什么呢?
  在Activity由前台转后台过程中,线程是一直在运行的,但是当Activity转入前台时会重新定义Runnable runnable;也就是说此时从message queue移除的runnable与原先加入message queue中的runnable并非是同一个对象。  解决方式1:如果把runnable定义为静态的则removeCallbacks不会失效,对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配,我们做如下修改就能解决上面的这个问题.

  解决方式2:将所有的runnable任务放到一个集合中,根据runnable的id移除相应的任务,即可以解决这个问题

2.timer的延时任务
同样用上面的demo来说明使用方法:
要注意的是:
TimerTask运行在一个单独的线程里,而不是UI线程。所以使用 Android timer时,注意android的单线程原则,确保线程安全。不要在TimerTask的run方法中做UI相关的操作,如:TextView.setText()等,这样可能会导致UI线程阻塞。如果需要可以使用handler向UI线程发消息,具体处理由UI线程自己完成。在使用完Timer之后,要使用Timer的cancel方法取消Timer,否则Timer一直在运行。

  这里需要注意的是,timer的cancel方法只能执行一次,不能在调用了cancel之后再进行timer的任务执行。

参考文章:
Android 定时器实现的几种方式和removeCallbacks失效问题详解

Android 中Timer和TimeTask完成定时任务

⑶ Android 实现定时任务的五种方式

1、普通线程sleep的方式,可用于一般的轮询Polling

      new Thread(new Runnable() {

            @Override

            public void run() {

                while (true) {

                    //todo

                    try {

                        Thread.sleep(iDelay);

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                }

            }

        }).start();

优点:非常简单的实现,逻辑清晰明了,也是最常见的写法

缺点:在sleep结束后,并不能保证竞争到cpu资源,这也就导致了下次执行时间必定>=iDelay,存在时间精度问题

2、Timer定时器

    //Timer + TimerTask结合的方法

    private final Timer timer = new Timer();

    private TimerTask timerTask = new TimerTask() {

        @Override

        public void run() {

            //todo

        }

    };

启动定时器方法:

timer.schele(TimerTask task, long delay, long period)

立即执行

timer.schele(timerTask, 0, 1000); //立刻执行,间隔1秒循环执行

延时执行

timer.schele(timerTask, 2000, 1000); //等待2秒后再执行,间隔1秒循环执行

关闭定时器方法:timer.cancel();

优点:纯正的定时任务,纯java SDK,单独线程执行,比较安全,而且还可以在运行过程中取消执行

缺点:基于单线程执行,多个任务之间会相互影响,多个任务的执行是串行的,性能较低,而且timer也无法保证时间精确度,是因为手机休眠的时候,无法唤醒cpu,不适合后台任务的定时

3、ScheledExecutorService

    private Runnable runnable2 = new Runnable() {

        @Override

        public void run() {

            //todo

        }

    };

    ScheledExecutorService executor = Executors.newScheledThreadPool(1);

    executor.scheleAtFixedRate(runnable2, 0, 1, TimeUnit.SECONDS);

关于scheleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) 方法说明:

command:需要执行的线程

initialDelay:第一次执行需要延时的时间,如若立即执行,则initialDelay = 0

period:固定频率,周期性执行的时间

unit:时间单位,常用的有MILLISECONDS、SECONDS和MINUTES等,需要注意的是,这个单位会影响initialDelay和period,如果unit = MILLISECONDS,则initialDelay和period传入的是毫秒,如果unit = SECONDS,则initialDelay和period传入的是秒

补充一下: 还有一个方法跟上面的很相似:scheleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit),这个也是带延迟时间的调度,并且也是循环执行,唯一的不同就是固定延迟时间循环执行,上面的是固定频率的循环执行。那这两者的区别?

举例子:

使用scheleAtFixedRate,任务初始延迟3秒,任务执行3秒,任务执行间隔为5秒:

        ScheledExecutorService executor = Executors.newScheledThreadPool(1);

        Log.e(TAG, "schele just start! time =" +  simpleDateFormat.format(System.currentTimeMillis()));

        executor.scheleAtFixedRate(new Runnable() {

            @Override

            public void run() {

                SystemClock.sleep(3000L);

                Log.e(TAG, "runnable just do it! time =" +  simpleDateFormat.format(System.currentTimeMillis()));

            }

        }, 3, 5, TimeUnit.SECONDS);

执行结果截图:

使用scheleWithFixedDelay,任务初始延迟3秒,任务执行3秒,任务执行延迟为5秒:

        ScheledExecutorService executor = Executors.newScheledThreadPool(1);

        Log.e(TAG, "schele just start! time =" +  simpleDateFormat.format(System.currentTimeMillis()));

        executor.scheleWithFixedDelay(new Runnable() {

            @Override

            public void run() {

                SystemClock.sleep(3000L);

                Log.e(TAG, "runnable just do it! time =" +  simpleDateFormat.format(System.currentTimeMillis()));

            }

        }, 3, 5, TimeUnit.SECONDS);

执行结果截图:

从这两者的运行结果就可以看到区别了:scheleAtFixedRate是相对于任务执行的开始时间,而scheleWithFixedDelay是相对于任务执行的结束时间。

优点:ScheledExecutorService是一个线程池,其内部使用的延迟队列,本身就是基于等待/唤醒机制实现的,所以CPU并不会一直繁忙。解决了Timer&TimerTask存在的问题,多任务处理时效率高

缺点:取消时需要打断线程池的运行,而且和外界的通信不太好处理

4、使用Handler中的postDelayed方法

    private Handler mHandler = new Handler();

    private Runnable runnable = new Runnable() {

        @Override

        public void run() {

            //todo

            mHandler.postDelayed(this, iDelay);

        }

    };

    mHandler.post(runnable); //立即执行

    mHandler.postDelayed(runnable, iDelay); //延时执行

    mHandler.removeCallbacks(runnable); //取消执行

优点:比较简单的android实现,适用UI线程

缺点:没想到,手动捂脸。。。。我估计是使用不当会造成内存泄露吧

5、Service + AlarmManger + BroadcastReceiver

⑷ android 后台运行 并定时触发任务

Android中的定时任务一般有两种实现方式,一种是使用Java
API里的Timer类,另一种是使用Android的Alarm机制。
这两种方式在多数情况下都能实现类似的效果,但Timer有一个明显的短板,它并不太适用与那些需要长期在后台运行的定时任务。As we
know,为了能让电池更加耐用,每种手机都会有自己的休眠策略:比如手机不用的时候智能的断开wifi连接,根据光线强弱自动调节屏幕亮度,根据手机长时间无操作时自动的让CPU进入到休眠状态等,当进入休眠状态时,这就有可能导致Timer中的定时任务无法正常运行。而Alarn机制则不存在这种情况,它具有唤醒CPU的功能,即可以保证每次需要执行定时任务的时候CPU都能正常工作。需要注意的是,这里的唤醒CPU和唤醒屏幕不是同一个概念,不能混淆。
这里我们只说Alarm机制的方式,代码如下:

public class AutoUpdateService extends Service {

@Override
public IBinder onBind(Intent intent) {

return null;
}

// 每次服务启动的时候调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {

@Override
public void run() {
doSomething();//这是定时所执行的任务
}
}).start();
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
int anHour =8 * 60 * 60 * 1000;// 这是8小时的毫秒数 为了少消耗流量和电量,8小时自动更新一次
long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
Intent intent2 = new Intent(this, AutoUpdateReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent2, 0);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);</span>

return super.onStartCommand(intent, flags, startId);
}
注意这里的AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);此处实现了定时任务。

首先我们通过调用Context的getSystemService()方法来获取AlarmManager的实例,这里需要传入的参数是ALARM_SERVICE.

接下来调用AlarmManager的set()方法就可以设置一个定时任务了,比如设定一个任务在5秒钟后执行,就可以写成 long
triggerAtTime = SystemClock.elapsedRealtime() + 5*1000;

manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,
pi);

其中第一个参数是一个整形参数,用于指定AlarmManager的工作类型,有四种值可以选,分别是
ELAPSED_REALTIME、ELAPSED_REALTIME_WAKEUP、RTC和RTC_WAKEUP。其中ELAPSED_REALTIME表示让定时任务的触发时间从系统开机开始算起,但不会唤醒CPU。ELAPSED_REALTIME_WAKEUP同样表示让定时任务的触发时间从系统开机开始算起,但会唤醒CPU。RTC表示让定时任务的触发时间从1970年1月1日0点开始算起,但不会唤醒CPU。RTC_WAKEUP同样表示让定时任务的触发时间从1970年1月1日0点开始算起,但会唤醒CPU。使用SystemClock.elapsedRealtime()方法可以获取到系统开机至今所经历时间的毫秒数,使用System.currentTimeMillis()方法可以获取到1970年1月1日0点至今所经历时间的毫秒数。
然后看一下第二个参数,这个参数就好理解多了,就是定时任务触发的时间,以毫秒为单位。如果第一个参数使用的是ELAPSED_REALTIME或ELAPSED_REALTIME_WAKEUP,则这里传入开机至今的时间再加上延迟执行的时间。如果第一个参数使用的是RTC或RTC_WAKEUP,则这里传入1970年1月1日0点至今的时间再加上延迟执行的时间。

第三个参数是一个PendingIntent,这里我们一般会调用getBroadcast()方法来获取一个能够执行广播的PendingIntent。这样当定时任务被触发的时候,广播接收器的onReceive()方法就可以得到执行。
当然设定一个任务在10秒钟后执行还可以写成:

longtriggerAtTime =
System.currentTimeMillis() + 10 * 1000;

manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,
pendingIntent);

然后创建PendingIntent指定处理定时任务的广播接收器AutoUpdateReceiver。

import service.AutoUpdateService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class AutoUpdateReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AutoUpdateService.class);
context.startService(i);
}

}
当启动AutoUpdateService后,就会在onStartCommand()方法里设定一个定时任务,这样每8个小时AutoUpdateReceiver的onReceive()方法就会得到执行,这样就又会启动AutoUpdateService服务,形成了永久的循环,保证服务每隔一段时间就会启动一次,这样就完成了一个长期在后台运行的服务。

我们在哪里启动服务呢,这要看具体的情况了,一般的话,当我们打开程序的时候启动一次就好了

比如写在Activity的onCrete()方法里
Intent
intent =new Intent(this,AutoUpdateService.class);

startService(intent);

最后,既然我们用到了服务和广播接收器,那么就得在AndroidManifest.xml中注册才行。

<service android:name="service.AutoUpdateService" ></service>
<receiver android:name="receiver.AutoUpdateReceiver"
></receiver>

本文参考资料:《第一行代码》

热点内容
ftp服务器被动模式配置 发布:2025-07-04 05:17:32 浏览:331
电动车小龟有哪些配置 发布:2025-07-04 05:16:18 浏览:39
mysql同步存储过程 发布:2025-07-04 05:14:32 浏览:662
安卓手机如何控制空调 发布:2025-07-04 05:09:06 浏览:154
新洁尔灭用于物体表面怎么配置 发布:2025-07-04 05:03:28 浏览:829
生活中的云服务器 发布:2025-07-04 05:01:55 浏览:744
三星g6700c原始密码是多少 发布:2025-07-04 04:49:41 浏览:726
网页编程代码 发布:2025-07-04 04:47:25 浏览:805
发消息时用到什么密码 发布:2025-07-04 04:41:47 浏览:980
3个密码箱能装多少钱 发布:2025-07-04 04:39:36 浏览:11