广告位联系
返回顶部
分享到

Android WorkManager实现后台定时任务流程介绍

Android 来源:互联网 作者:佚名 发布时间:2023-01-31 20:22:25 人浏览
摘要

WorkManager和Service并不相同,也没有直接的联系。Service是Android系统四大组件之一,它没有被销毁的情况下是一直保持在后台运行的。而WorkManager只是一个处理定时任务的工具,它可以保证

WorkManager和Service并不相同,也没有直接的联系。Service是Android系统四大组件之一,它没有被销毁的情况下是一直保持在后台运行的。而WorkManager只是一个处理定时任务的工具,它可以保证即使在应用退出甚至手机重启的情况下,之前注册的任务仍然将会得到执行,因此WorkManager很适合用于执行一些定期和服务器进行交互的任务,比如周期性地同步数据等等。

使用WorkManager注册的周期性任务不能保证一定会准时执行,这是因为系统为了减少电量消耗,可能会将触发时间临近的几个任务放在一起执行,这样可以大幅度减少CPU被唤醒的次数,从而有效延长电池的使用时间。

WorkManager的基本用法

先添加依赖

 implementation 'androidx.work:work-runtime-ktx:2.2.0'

WorkManager的基本用法主要分为以下3步:

  • 定义一个后台任务,并实现具体的任务逻辑
  • 配置该后台任务的运行条件和约束信息,并构建后台任务请求
  • 将该后台任务请求传入WorkManager的enqueue()方法中,系统会在合适的时间运行

第一步定义一个后台任务,这里创建一个SimpleWorker类,代码如下所示:

1

2

3

4

5

6

class SimpleWorker(context: Context,params:WorkerParameters):Worker(context,params) {

    override fun doWork(): Result {

        Log.d("SimpleWorker", "do Work in SimpleWorker")

        return Result.success()//成功就返回Result.success()

    }

}

首先每一个后台任务都必须继承自Worker类,并调用它唯一的构造函数。然后重写父类中的doWork()方法,在这个方法中编写具体的后台任务逻辑。

第二步配置该后台任务的运行条件和约束信息

1

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()

可以看到,只需要把刚才创建的后台任务所对应的Class对象传入 OneTimeWorkRequest.Builder的构造函数当中,然后调用build()方法就可以完成构建。

OneTimeWorkRequest.Builder是WorkRequest.Builder的子类,用于构建单次运行的后台任务请求。WorkRequest.Builder还有另外一个子类PeriodicWorkRequest.Builder,可用于构建周期性运行的后台任务请求,但是为了降低设备性能消耗,PeriodicWorkRequest.Builder构造函数中传入的运行周期间隔不能短于15分钟,示例代码如下:

1

PeriodicWorkRequest.Builder(SimpleWorker::class.java,15,TimeUnit.MINUTES).build()

最后一步,将构建出来的后台任务请求传入WorkManager的enqueue()方法中,系统就会在合适的时间去运行

1

WorkManager.getInstance(this).enqueue(request)

布局增加一个按钮

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<?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:layout_width="match_parent"

       android:layout_height="wrap_content"

       android:id="@+id/doWorkBtn"

       android:layout_gravity="center_horizontal"

       android:text="Do Work"

       />

</LinearLayout>

修改MainActivity

1

2

3

4

5

6

7

8

9

10

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        doWorkBtn.setOnClickListener {

            val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()

            WorkManager.getInstance(this).enqueue(request)

        }

    }

 }

点击按钮后,SimpleWorker打印日志

使用WorkManager处理复杂的任务

首先让后台任务在指定的延迟时间后运行,只需要借助setInitialDelay()方法就可以了,代码如下:

1

2

3

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)

              .setInitialDelay(5,TimeUnit.MINUTES)

              .build()

这就表示我们希望让SimpleWorker这个后台任务在5分钟后运行。

当我们给后台任务请求添加标签时,可以这样写

1

2

3

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)

    .addTag("simple")

    .build()

添加标签最主要的一个功能就是通过标签取消后台任务请求

1

WorkManager.getInstance(this).cancelAllWorkByTag("simple")

也可以通过id来取消后台任务请求:

1

WorkManager.getInstance(this).cancelWorkById(request.id)

但是使用id只能取消单个后台任务请求,而使用标签的话,则可以将同一标签名的所有后台任务请求全部取消,这个功能在逻辑复杂的场景尤其有用。

除此之外,还可以使用如下代码一次性取消所有后台任务请求:

1

WorkManager.getInstance(this).cancelAllWork()

如果后台任务的doWork()方法中返回了Result.retry()那么是可以结合setBackoffCriteria()方法来重新执行任务的,具体代码如下:

1

2

3

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)

    .setBackoffCriteria(BackoffPolicy.LINEAR,10,TimeUnit.SECONDS)

    .build()

setBackoffCriteria()方法接收3个参数:第二个和第三个参数用于指定在多久之后重新执行任务,时间最短不能少于10秒钟;第一个参数用于指定如果任务再次执行失败,下次重试的时间应该以什么样的形式延迟。第一个参数的可选值有两种,分别是LINEAR和EXPONENTIAL,前者表示下次重试时间以线性的方式延迟,后者代表下次重试时间以指数的方式延迟。

而doWork()方法中返回的Result.success()和Result.failure()又有什么作用?这两个返回值其实就是用于通知任务运行结果的,我们可以使用如下代码进行监听:

1

2

3

4

5

6

7

8

9

WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).

observe(this){

    workInfo->

    if(workInfo.state==WorkInfo.State.SUCCEEDED){

        Log.d(TAG, "do work succeeded")

    }else if(workInfo.state==WorkInfo.State.FAILED){

        Log.d(TAG, "do work failed")

    }

}

这里调用了getWorkInfoByIdLiveData()方法,并传入后台任务请求的id,会返回一个LiveData对象。然后我们就可以调用LiveData对象的observe()方法来观察数据变化了,以监听后台任务的运行结果。

另外,还可以调用getWorkInfoByTagLiveData()方法,监听同一标签名下所有后台任务请求的运行结果。

WorkManager还有一个特色的功能—链式任务

假设这里定义了3个独立的后台任务:同步数据、压缩数据和上传数据。现在我们想要实现先同步、再压缩、最后上传的功能,就可以借助链式任务来实现,代码示例如下:

1

2

3

4

5

6

7

8

val sync=...

val compress=...

val upload=...

WorkManager.getInstance(this)

.beginWith(sync)

.then(compress)

.them(upload)

.enqueue()

beginWith()方法用于开启一个链式任务,至于后面要接上什么样的后台任务,只需要使用then()方法来连接即可。另外WorkManager还要求,必须在前一个后台任务运行成功之后,下一个后台任务才会运行。也就是说,如果某个后台任务运行失败,或者被取消了,那么接下来的后台任务就得不到运行了。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/ChenYiRan123456/article/details/128740405
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计