本次博客主要针对 定时任务 这一块做了一下梳理其用法。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33706840/article/details/79239784

前言

本次博客主要针对 定时任务 这一块做了一下梳理其用法。

Android 中的定时任务一般有两种实现方式,一种是Java API 里提供的 Timer 类,
一种是使用 Android 的 Alarm 机制。这两种方式在多数情况下都能实现类似的效果,但 Timer
它并不太适用于那些需要长期在后台运行的定时任务。为
了能让电池更加耐用,每种手机都会有自己的休眠策略,Android 手机就会在长时间不操作。
的情况下自动让 CPU 进入到睡眠状态,这就有可能导致 Timer 中的定时任务无法正常运行。
而 Alarm 机制则不存在这种情况,它具有唤醒 CPU 的功能,即可以保证每次需要执行定时
任务的时候 CPU 都能正常工作

Timer用法

TimerTimerTask

  Timer是java中定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。

  TimerTask是一个实现了Runnable接口的抽象类,可以被Timer执行的任务。

直接上Demo

public class MainActivity extends AppCompatActivity {

private TimerTask mTimerTask;
private Timer mTimer;
private TextView mTv;
private int count = 0;
private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        int count = msg.arg1;
        mTv.setText(count + "");
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTv = findViewById(R.id.tv);
    mTimer = new Timer();
    mTimerTask = new TimerTask() {
        @Override
        public void run() {
            Message message = Message.obtain();
            message.arg1 = count;
            count++;
            mHandler.sendMessage(message);
        }
    };
    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mTimer.schedule(mTimerTask, 1000,1000);
        }
    });
}
}

程序执行结果为每隔一秒TextView的数值加一,通过Handler来实现线程间通信,这里不再详述Handler

首先我们通过new关键字可以得到Timer对象和TimerTask对象并重写TimerTaskrun方法,里面可以做一些你想做的逻辑操作,然后通过Handler发送消息,重写 handleMessage(Message msg)
在这里做一些更新UI的操作。

当我们需要结合服务一起使用时,我们都知道服务里是不可以做耗时操作的,Service耗时操作为20秒,我们可以使用IntentService,或者通过广播结合服务一起使用,这里就不再详述。

Alarm 机制的用法

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

获取一个 AlarmManager 的实例:

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

调用 AlarmManager 的 set()方法设置一个定时任务,例如设定一
个任务在 5 秒钟后执行的方法:

long delayTime = SystemClock.elapsedRealtime() + 10 * 1000;
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);

第一个参数是一个整型参数,用于指定 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()方法就可以得到执行。

长期在后台执行定时任务的服务。创建一个 ServiceBestPractice 项目,然后新增一个 LongService
类,代码如下所示:

 public class LongService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Log.i("LongService", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "执行");
        }
    }).start();
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    long triggerAtTime = SystemClock.elapsedRealtime() + 5 * 1000;
    Intent intent1 = new Intent(this, LongBroadcastReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent1, PendingIntent.FLAG_CANCEL_CURRENT);
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
    return super.onStartCommand(intent1, flags, startId);
}

@Override
public void onDestroy() {
    super.onDestroy();
}
}

新建一个 LongBroadcastReceiver 类,并让它继承自 BroadcastReceiver,代码如下所示:

public class LongBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    Intent intent1 = new Intent(context,LongService.class);
    context.startService(intent1);
}
}

onReceive()方法里构建出了一个 Intent 对象,然后去启动
LongService 这个服务。

MainActivity 中的代码,如下所示:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent intent = new Intent(this,LongService.class);
    startService(intent);
}
}

最后服务和广播接收器都要在 AndroidManifest.xml 中注册,

 `<application`
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".LongService"></service>
    <receiver android:name=".LongBroadcastReceiver"></receiver>
</application>

然后观察 LogCat打印日志。

Android 4.4 版本开始,Alarm 任务的触发时间将会变得不准确,
有可能会延迟一段时间后任务才能得到执行。这并不是个 bug,而是系统在耗电性方面进行
的优化。系统会自动检测目前有多少 Alarm 任务存在,然后将触发时间将近的几个任务放在
一起执行,这就可以大幅度地减少 CPU 被唤醒的次数,从而有效延长电池的使用时间。
当然,如果你要求 Alarm 任务的执行时间必须准备无误,Android 仍然提供了解决方案。
使用 AlarmManager 的 setExact()方法来替代 set()方法,就可以保证任务准时执行了。

Alarm参考第一行代码

菜鸟学习中…有错望指正!谢谢

猜你喜欢

转载自blog.csdn.net/qq_33706840/article/details/79239784
今日推荐