WorkManager概述及运用
WorkManager一、概述WorkManager是针对一些即使App退出了也要由系统确保运行的任务设计的,可以延迟执行后台任务,提供了电量友好型APIWorkManager可以轻松让异步任务延迟执行以及何时运行他们。我们可以给WorkManager设置一个任务,然后选择相应运行的环境,并在符合条件时将其交给WorkManager运行,即使该应用被强制退出,此任务仍可保证运行。WorkManag
WorkManager
一、概述
WorkManager是针对一些即使App退出了也要由系统确保运行的任务设计的,可以延迟执行后台任务,提供了电量友好型API
WorkManager可以轻松让异步任务延迟执行以及何时运行他们。我们可以给WorkManager设置一个任务,然后选择相应运行的环境,并在符合条件时将其交给WorkManager运行,即使该应用被强制退出,此任务仍可保证运行。
WorkManager在应用运行时执行任务会开一个新线程执行,在应用未运行时会自动选择JobScheduler、Firebase JobDispatcher或AlarmManager。WorkManager会自动选择最佳选项
二、依赖
dependencies {
// (Java only)
implementation 'androidx.work:work-runtime:2.5.0'
// Kotlin + coroutines
implementation 'androidx.work:work-runtime-ktx:2.5.0'
// optional - RxJava2 support
implementation 'androidx.work:work-rxjava2:2.5.0'
// optional - GCMNetworkManager support
implementation 'androidx.work:work-gcm:2.5.0'
// optional - Test helpers
androidTestImplementation 'androidx.work:work-testing:2.5.0'
// optional - Multiprocess support
implementation 'androidx.work:work-multiprocess:2.5.0'
}
三、内部类
· Worker:指定我们需要执行的任务
· WorkRequest:代表一个单独具体的任务。一个WorkRequest对象指定某个Worker类应该执行该任务。同时可以向WorkRequest对象中添加详细信息,指定任务运行的环境。每个WorkManager都有一个自动生成的唯一ID,我们可以使用此ID执行取消排队或者获取任务状态等内容。我们一般使用WorkManager的子类:OneTimeWorkRequest或PeriodicWorkRequest
· WorkRequest.Builder:用于创建WorkRequest对象。常用OneTimeWorkRequest.Builder或PeriodicWorkRequest.Builder
· Constraints:指定任务何时何状态运行。我们通过Constraints.Builder创建Constraints对象,并在创建WorkRequest前将Constraints对象传递给WorkRequest.Builder
· WorkManager:将WorkRequest入队并管理。我们将WorkRequest对象传递给WorkManager,由WorkManager同意调度并遵守我们约定的约束条件
· WorkStatus:包含有关特定任务的信息。WorkManager为每个WorkRequest对象提供一个LiveData,LiveData持有一个WorkStatus,通过观察LiveData确认任务的当前状态
四、基本用法
基本用法分为3步:
- 定义后台任务,并实现相关逻辑
- 配置该后台任务的运行条件和约束条件
- 构建后台任务请求
定义后台任务,并实现相关逻辑
定义自己的Worker类继承自Worker类并重写doWork方法
doWork方法指定Worker类如何执行操作,但是不能出现任何关于任务何时运行的信息
class myWorker(context: Context, params: WorkerParameters) : Worker(context, params){
override fun doWork() : Result{
//执行操作
return Result.success()
}
}
配置该后台任务的运行条件和约束条件
在MainActivity中根据myWorker类创建OneTimeWorkRequest对象
val myConstraints = Constraints.Builder().build()
val myRequest = OneTimeWorkRequest.Builder(myWorker::class.java)
.setConstraints(myContraints)
.build()
OneTimeWorkRequest.Builder用于构建单次运行的后台任务请求
PeriodicWorkRequest.Builder用于构建周期运行的后台任务请求,且运行间隔不能短于15 mins
在创建Constraints和创建WorkRequest时可以配置各种各样的运行条件和约束条件
构建后台任务请求
在MainActivity中将该后台任务请求传入WorkManager的enqueue方法。
WorkManager.getInstance(this).enqueue(myRequest)
检查任务状态方法:
WorkManager.getInstance(this).getWorkInfoByIdLiveData(myRequest.id)
.observe(this){ workInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED){
//利用workInfo对结果进行判断
}
}
取消任务方法:
WorkManager.getInstance(this).cancelByWorkId(myRequest.id)
整体如下:
class MainActivity : AppcompatActivity(){
@SuppressLint("EnqueueWork")
override fun onCreate(saveInstanceState: Bundle?){
...
val myConstraints = Constraints.Builder().build()
val myRequest = OneTimeWorkRequest.Builder(myWorker::class.java)
.setConstraints(myContraints)
.build()
WorkManager.getInstance(this).enqueue(myRequest)
WorkManager.getInstance(this).getWorkInfoByIdLiveData(myRequest.id)
.observe(this){ workInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED){
//利用workInfo对结果进行判断
}
}
WorkManager.getInstance(this).cancelByWorkId(myRequest.id)
}
}
含参Worker类
使用键值对和Data对象进行参数的输入和结果的返回。
在主函数中通过观察任务的WorkStatus获取输出
TestWorker类
class TestWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
companion object{
const val KEY_INT_ARG = "INT"
const val KEY_STR_ARG = "STR"
const val KEY_LIST_ARG = "LIST"
const val KEY_CLASS_ARG = "CLASS"
const val KEY_RESULT = "RESULT"
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
//获取参数
val int = inputData.getInt(KEY_INT_ARG, 0)
println("int:$int.toString()")
val str = inputData.getString(KEY_STR_ARG)
/**
* 仅传递基础数据类型和其构成的数组
* 对于类和类组成的数组,需要使用Gson转换成json字符串
* Gson依赖:implementation 'com.google.code.gson:gson:2.8.6'
*/
val list: ArrayList<TestClass> = Gson().fromJson(
inputData.getString(KEY_LIST_ARG),
object : TypeToken<ArrayList<TestClass>>() {}.type
)
val cls: TestClass = Gson().fromJson(
inputData.getString(KEY_CLASS_ARG),
object : TypeToken<TestClass>() {}.type
)
//对参数进行操作
println("TestWorker:")
println("int:$int.toString()")
println("str:$str")
for (item in list){
println("list:${item.text}")
}
println("class:${cls.text}")
//返回值
val listString = Gson().toJson(list)
val result = Data.Builder().putString(KEY_RESULT, listString).build()
return Result.Success(result)
}
}
主函数
class MainActivity : AppCompatActivity() {
@SuppressLint("EnqueueWork")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//非基本类型参数转换成String
val cls = TestClass("TestClass")
val clsString = Gson().toJson(cls)
val list = ArrayList<TestClass>()
list.add(TestClass("TestClass1"))
list.add(TestClass("TestClass2"))
list.add(TestClass("TestClass3"))
val listString = Gson().toJson(list)
//创建参数
val myData = Data.Builder().putInt(TestWorker.KEY_INT_ARG, 999)
.putString(TestWorker.KEY_STR_ARG, "String")
.putString(TestWorker.KEY_CLASS_ARG, clsString)
.putString(TestWorker.KEY_LIST_ARG, listString)
.build()
//构建后台
val work = OneTimeWorkRequest.Builder(TestWorker::class.java)
.setInputData(myData)
.build()
WorkManager.getInstance(this).enqueue(work)
//获得返回值
WorkManager.getInstance(this).getWorkInfoByIdLiveData(work.id)
.observe(this){workInfo ->
val str = workInfo.outputData.getString(TestWorker.KEY_RESULT)
if (str != null){
val result: ArrayList<TestClass> = Gson().fromJson(str, object : TypeToken<ArrayList<TestClass>>() {}.type)
for (item in result){
println("result:${item.text}")
}
}
}
}
}
链式任务
WorkManager允许我们创建和排队多个任务的工作序列,以及它们按照什么顺序运行。
任何一个任务返回Work.WorkResult.FAILURE,整个序列结束
WorkManager.getInstance(this).beginWith(workA)
.then(workB)
.then(workC)
.enqueue()
允许多个对象传递给begin()和then()
WorkManager并行运行同一次方法传进的任务
WorkManager.getInstance(this).beginWith(listOf(workerA1, workerA2, workerA3))
.then(listOf(workerB1, workerB2))
.then(workerC)
.enqueue()
允许使用WorkContinuation.combine方法连接多个链
WorkManager根据连接链的顺序依次运行。
链内任务按顺序执行
链间任务可能重叠导致任务顺序的改变。
val chain1 = WorkManager.getInstance(this)
.beginWith(workerA1)
.then(workerB1)
val chain2 = WorkManager.getInstance(this)
.beginWith(workerA2)
.then(workerB2)
WorkContinuation.combine(listOf(chain1, chain2))
.then(workerC)
.enqueue()
更多推荐
所有评论(0)