Jetpeck从入门到几乎入门(五)

1,145 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

Jetpeck从入门到几乎入门(五)

前言

Jetpack系列:

Jetpack从入门到几乎入门(一) - 掘金 (juejin.cn)

Jetpack从入门到几乎入门(二) - 掘金 (juejin.cn)

Jetpack从入门到几乎入门(三) - 掘金 (juejin.cn)

本文是我在学习guolin大神的《第一行代码》第三版Jetpack部分的Room的知识总结,文中部分代码参考自《第一行代码》第三版

在阅读本文前,您需要掌握kotlin语言的基本语法,并且了解什么是LifeCycle

帮助编写后台代码的组件——WorkManager

简介

不知从何时开始,与后台相关的API变更越来越频繁,为了使后台代码能在不同系统版本上保证兼容性,Google 推出了WorkManager 组件。

WorkManager 适合用于处理一些要求定时执行的任务,它可以根据操作系统的版本自动选择底层是使用AlarmManager 实现还是JobScheduler 实现。

与AsyncTask, ThreadPool, RxJava的不同

使用这三个工具确实能帮助我们在后台线程实现一些功能,不过应用一被杀掉就干不了活了。WorkManager的不同之处在于,它在应用被杀, 甚至设备重启后仍能保证任务的执行。这一特性也决定了它的应用场景,WorkManager适合处理那些必须完成并且可以延迟的后台工作。

WorkManager的使用

首先在app/build.gradle 文件中添加依赖

dependencies {
 def work_version = "1.0.0-beta02"
 implementation "android.arch.work:work-runtime-ktx:$work_version"
}

在依赖添加完成后,我们先添加一个任务。我们先创建一个SimpleWorker类。

class SimpleWorker(context: Context,params: WorkerParameters):Worker(context,params) {
    //doWork()方法不会运行在主线程中,我们可以放心实现各种逻辑
    override fun doWork(): Result {
        Log.d("SimpleWorker", "do work in SimpleWorker")
        return Result.success()//返回示任务的运行结果
    }
}

每个后台任务都必须继承Worker类,我们可以在doWork()方法中编写后台任务的逻辑。

在定义好后台任务后,我们可以配置该后台任务的运行条件。

在Activity中配置

 binding.doWorkBtn.setOnClickListener{
            //val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()//单次任务请求
            val request = PeriodicWorkRequest.Builder(SimpleWorker::class.java, 15,
                TimeUnit.MINUTES).build()//构造函数中传入的运行周期间隔不能短于15 分钟
​
        }

PeriodicWorkRequest.Builder,可用于构建周期性运行的后台任务请求。

最后,将后台任务传入WorkManager的enqueue()方法中

WorkManager.getInstance(context).enqueue(request)

WorkManager处理复杂的任务

让后台任务在指定的延迟时间后运行

需借助setInitialDelay()方法

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
                .setInitialDelay(5,TimeUnit.MINUTES)
                .build()

我们还可以给后台任务请求添加标签

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
                .setInitialDelay(5,TimeUnit.MINUTES)
                .addTag("simple")
                .build()

在没有标签时,可以通过id来取消后台任务请求,使用标签后不仅可以取消单个任务,还可以将同一标签名的所有后台任务请求全部取消:

WorkManager.getInstance(this).cancelWorkById(request.id)//通过ID
WorkManager.getInstance(this).cancelAllWorkByTag("simple")//通过标签
WorkManager.getInstance(this).cancelAllWork()//一次性取消所有请求

doWork()方法中返回了Result.retry()后,可以通过setBackoffCriteria()方法来重新执行任务

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
 ... 
 .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS)//每隔10秒重新执行任务
 .build()

上面的代码实现的功能是每隔10秒重新执行任务,传入的时间最短不能少于10 秒钟。第一个参数则用于指定如果任务再次执行失败,下次重试的时间应该以什么样的形式延迟。第一个参数的可选值有两种,分别是LINEAR和EXPONENTIAL,前者代表下次重试时间以线性的方式延迟,后者代表下次重试时间以指数的方式延迟。

对后台任务的运行结果进行监听

我们需要调用getWorkInfoByIdLiveData()方法得到LiveData对象,通过LiveData对象的observe()方法来观察数据变化,实现监听。

WorkManager.getInstance()
                .getWorkInfoByIdLiveData(request.id)
                .observe(this, android.arch.lifecycle.Observer {  workInfo ->
                    if (workInfo != null) {
                        if (workInfo.state == WorkInfo.State.SUCCEEDED) {
                            Log.d("MainActivity", "do work succeeded")
                        } else if (workInfo.state == WorkInfo.State.FAILED) {
                            Log.d("MainActivity", "do work failed")
                        }
                    }
                })

WorkManager的特色功能——链式任务

val sync = ... 
val compress = ... 
val upload = ... 
WorkManager.getInstance() 
 .beginWith(sync) //可添加多个任务
 .then(compress) 
 .then(upload) 
 .enqueue()

在上述代码中,我们定义了3个独立的后台任务。beginWith()方法用于开启一个链式任务,then()方法连接不同任务。值得注意的是,要在一个任务执行完毕后才能执行下一个任务

总结

推荐处理的工作

  1. 立即执行:必须立即开始且很快就完成的任务,可以加急
  2. 长时间运行:运行时间可能较长(有可能超过 10 分钟)的任务。
  3. 可延期执行:延期开始并且可以定期运行的预定任务。

这就是 WorkManager API 的基础知识,相信你已经可以了解到WorkManager的使用。