- 前言
- 概述
- 基本使用
- 依赖库
- 简单后台任务使用
- 业务复杂后台任务使用
你若需要时间,还得自己把他造出来。 喝汤能补 (* ^ ▽ ^ *)
前言
该文章作为学习交流,如有错误欢迎各位大佬指正 (* ^ ▽ ^ *)
- 本文简介
主要讲解:WorkManager的使用,以及相关API的使用。
概述
在介绍WorkManager前,先来了解下Android系统的后台历史。在早期的时候,Android系统后台功能非常开放,优先级高,仅次于Activity,所以每个应用都想无限地占用后台资源,导致手机内存紧张,耗电也快,以及越发卡。后期Android系统每发布一个新版本,后台权限都会被限制。
- 4.4系统开始AlarmManager的触发时间由原来的精准变为不精准;5.0系统中加入了JobScheduler来处理后台任务;6.0系统中引入Doze和App Standby模式用于降低手机被后台唤醒的频率;从8.0系统开始直接禁用了Service的后台功能,只允许使用前台Service。
- 在国产手机上,WorkManager功能可能得不到正确运行。因为多数厂商手机在定制系统时,会增加一键关闭的功能,允许用户杀死所以非白名单的应用。被杀死的的应用就无法接受广播,也就无法运行WorkManager后台任务。
- WorkManager可以用,但不要使用它实现核心功能,因为在国产手机上可能非常不稳定。
虽然,这样能不断优化Android系统的卡顿问题,但是也导致开发者很难在不同的系统版本上为应用进行兼容处理。这时,就需要使用WorkManager来进行简化。
WorkManager组件,适合用于处理一些要求定时执行的任务,它能根据系统的版本自动选择底层使用AlarmManager还是JobScheduler实现,从而减少开发者的兼容工作。还支持周期性任务、链式任务处理等功能。
- WorkManager与Service并不相同,没有直接联系。Service是Android系统四大组件之一,没有被销毁的情况下是一直保持在后台运行的。WorkManager是一个处理定时任务的工具,可以保证在应用退出,或手机重启下,之前注册的任务仍会执行。
- WorkManager很适合执行一些定期和服务器进行交互的任务,比如周期性地同步数据等场景
- WorkManager注册的周期性任务不能保证一定会准时执行,因系统为了减少电量消耗和CPU被唤醒的次数,可能会将触发时间临近的几个任务放在一起执行。
- 使用步骤:
(1)自定义后台任务类,必须继承Worker,并调用唯一的构造函数,重写doWork()方法,该方法中就是具体的任务逻辑。
(2)然后使用WorkRequest的子类构建后台任务的运行条件。
(3)将该后台任务请求传入WorkManage的enqueue() 方法中,系统在合适时间运行。WorkManager对象需要WorkManager.getInstance(Context对象)得到 - doWork() 不在主线程中,可执行耗时任务。要求返回Result对象,成功是Result.success();失败是Result.failure();UI层可通过WorkManager中的getWorkInfoByIdLiveData()函数进行来监听成功与失败。Result.retry()也是失败,不过可结合WorkRequest的setBackoffCriteria()函数重新执行任务。
- OneTimeWorkRequest是WorkRequest的子类,用于构建单次运行的后台任务请求。OneTimeWorkRequest.Builder(自定义后台类的Class对象).build()
- PeriodicWorkRequest是WorkRequest的子类,用于构建周期性运行的后台任务请求。且因降低设备性能消耗,周期性间隔不能短于15分钟。PeriodicWorkRequest.Builder(自定义后台类的Class对象,周期性间隔时间,时间的单位).build()
- setInitialDelay(延迟时间,时间的单位) 让后台任务在指定延迟时间后运行。
- addTag(标签的名称) 用于给后台任务请求添加标签。标签的主要作用,可以通过标签来取消后台任务请求,只有是该标签的任务都可以取消
- 取消后台任务,WorkManager类中的cancelAllWorkByTag(请求任务的标签),cancelWorkById(请求任务的对象的id),cancelAllWork() 取消所以后台任务。WorkManager的对象,使用WorkManager.getInstance(Context对象)得到。
- setBackoffCriteria() ,当doWork()方法返回Result.retry()时,可以通过该方法请求执行任务。该方法的参数:第一个是用于指定如果任务再次执行失败,下次重试的时间以什么样的形式延迟;第二个和第三个参数,用于指定多久之后重新执行任务,时间最短不少于10秒钟。第一个参数的值:LINEAR代表下次重试时间以线性方式延迟,EXPONENTIAL代表下次重试时间以指数的 方式延迟。
如果任务一直失败,那重试就无意义,这时频繁重试就会增加设备消耗。如果失败次数增多,重试时间也进行延迟,就能合理的降低性能消耗 - WorkManager中的getWorkInfoByIdLiveData(请求任务的对象的id) 或getWorkInfosByTagLiveData(请求任务的标签) 来监听请求任务执行结果(Result的State中的状态)
- WorkManager中的链式调用,beginWith开启一个链式任务,then连接任务。必须在前一个后台任务执行成功后,下一个任务才会执行。 如果某个任务执行失败,或者被取消,则后面的任务都不会执行。
WorkManager.getInstance(Context对象)
.beginWith(请求任务WorkRequest子类对象)
.then(请求任务WorkRequest子类对象)
.then(请求任务WorkRequest子类对象)
.enqueue()
基本使用
依赖库
在app/build.gradle文件中添加依赖库。
android {
//...
}
dependencies {
implementation "androidx.work:work-runtime:2.4.0"
}
简单后台任务使用
大致的使用步骤
(1)定义一个后台任务,并实现具体的任务逻辑
自定义后台任务类,必须继承Worker,并调用唯一的构造函数,重写doWork()方法,该方法中就是具体的任务逻辑。
(2)配置后台任务的运行条件和约束信息,并构建后台任务请求
分为两种方式:
OneTimeWorkRequest是WorkRequest的子类,用于构建单次运行的后台任务请求。
PeriodicWorkRequest是WorkRequest的子类,用于构建周期性运行的后台任务请求。且因降低设备性能消耗,周期性间隔不能短于15分钟。
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
val requestTime = PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,
TimeUnit.MINUTES).build()
(3)将该后台任务请求传入WorkManage的enqueue()方法中,系统在合适时间运行。
使用WorkManager.getInstance(Context对象).enqueue(WorkRequest子类的实例对象)
简单示例代码
主要功能:定义后台任务,并打印一段日志。
class SimpleWorker(context: Context,params: WorkerParameters): Worker(context,params) {
override fun doWork(): Result {
Log.e("bluePlus"," do work in SimpleWorker ")
return Result.success()
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_work_manager)
doWorkBtn.setOnClickListener {
// 单次请求任务
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
// 周期性请求任务
val requestTime = PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,
TimeUnit.MINUTES).build()
WorkManager.getInstance(applicationContext).enqueue(request)
}
}
业务复杂后台任务使用
在复杂的业务面前,需要编写对应的后台任务处理逻辑。比如:延时后台任务的处理,取消后台任务后台任务重新执行等等
- setInitialDelay(延迟时间,时间的单位) 让后台任务在指定延迟时间后运行。
- addTag(标签的名称) 用于给后台任务请求添加标签。标签的主要作用,可以通过标签来取消后台任务请求,只有是该标签的任务都可以取消
- 取消后台任务,WorkManager类中的cancelAllWorkByTag(请求任务的标签),cancelWorkById(请求任务的对象的id),cancelAllWork() 取消所以后台任务。WorkManager的对象,使用WorkManager.getInstance(Context对象)得到。
- setBackoffCriteria() ,当doWork()方法返回Result.retry()时,可以通过该方法请求执行任务。该方法的参数:第一个是用于指定如果任务再次执行失败,下次重试的时间以什么样的形式延迟;第二个和第三个参数,用于指定多久之后重新执行任务,时间最短不少于10秒钟。第一个参数的值:LINEAR代表下次重试时间以线性方式延迟,EXPONENTIAL代表下次重试时间以指数的 方式延迟。
如果任务一直失败,那重试就无意义,这时频繁重试就会增加设备消耗。如果失败次数增多,重试时间也进行延迟,就能合理的降低性能消耗 - WorkManager中的getWorkInfoByIdLiveData(请求任务的对象的id) 或getWorkInfosByTagLiveData(请求任务的标签) 来监听请求任务执行结果(Result的State中的状态)
- WorkManager中的链式调用,beginWith开启一个链式任务,then连接任务。必须在前一个后台任务执行成功后,下一个任务才会执行。 如果某个任务执行失败,或者被取消,则后面的任务都不会执行。
WorkManager.getInstance(Context对象)
.beginWith(请求任务WorkRequest子类对象)
.then(请求任务WorkRequest子类对象)
.then(请求任务WorkRequest子类对象)
.enqueue()
简单的例子了解相关方法的用法
主要的是了解相关方法是如何调用的。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_work_manager)
// 单次请求任务
val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
// .setInitialDelay(5,TimeUnit.MINUTES) //延时处理
.addTag("simple") //添加标签
.setBackoffCriteria(BackoffPolicy.LINEAR,10,TimeUnit.MINUTES)
.build()
// 周期性请求任务
val requestTime = PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,
TimeUnit.MINUTES).build()
doWorkBtn.setOnClickListener {
//1.WorkManager的普通调用
WorkManager.getInstance(applicationContext).enqueue(request)
// WorkManager.getInstance(applicationContext).cancelAllWorkByTag("simple") //通过标签取消
// WorkManager.getInstance(applicationContext).cancelWorkById(request.id) //通过id取消
// WorkManager.getInstance(applicationContext).cancelAllWork() //取消全部任务
//2.WorkManager的链式调用
val sync = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
val compress = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
val upload = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()
WorkManager.getInstance(this)
.beginWith(sync)
.then(compress)
.then(upload)
.enqueue()
}
// 监听请求任务的结果
WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id)
.observe(this){ workInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED){
Log.e("bluePlus"," do work succeeded ")
}else if (workInfo.state == WorkInfo.State.FAILED){
Log.e("bluePlus"," do work Failed ")
}
}
}
}
class SimpleWorker(context: Context,params: WorkerParameters): Worker(context,params) {
override fun doWork(): Result {
Log.e("bluePlus"," do work in SimpleWorker ")
// return Result.retry()
// return Result.failure()
return Result.success()
}
}
// UI界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/doWorkBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Do Work"/>
</LinearLayout>
觉得有帮助的点下赞哟,毕竟三连步骤更多,嘻嘻,谢谢大家的支持(* ^ ▽ ^ *)