WorkManager 在 Kotlin 中的实践

浩浩 等级 551 0 0

WorkManager 是一个 Android Jetpack 扩展库,它可以让您轻松规划那些可延后、异步但又需要可靠运行的任务。对于绝大部分后台执行任务来说,使用 WorkManager 是目前 Android 平台上的最佳实践。

在这篇文章中,我们将讨论:

Kotlin 版的 WorkManager

本文的示例代码是用 Kotlin 编写的并使用了 KTX 库 (Kotlin Extensions)。KTX 版的 WorkManager 提供了更简洁且惯用的 Kotlin 扩展函数。如 WorkManager 发布日志中描述的那样,只需要在 build.gradle 文件中添加 androidx.work:work-runtime-ktx 依赖项,即可使用 KTX 版的 WorkManager。该组件包含 CoroutineWorker 和其他有用的 WorkManager 扩展方法。

更简洁且惯用

当您需要构造一个数据对象,并且需要将它传入Worker 类或者从 Worker 类返回时,KTX 版 WorkManager 提供了一种语法糖。在这种情况下,用 Java 语法实现的代码如下所示:


Data myData = new Data.Builder()
                      .putInt(KEY_ONE_INT, aInt)
                      .putIntArray(KEY_ONE_INT_ARRAY, aIntArray)
                      .putString(KEY_ONE_STRING, aString)
                      .build();

而在 Kotlin 中,我们可以借助 workDataOf 辅助函数将代码写的更简洁:


inline fun workDataOf(vararg pairs: Pair<String, Any?>): Data

因此可以将前面的 Java 表达式改写成:


val data = workDataOf(
        KEY_MY_INT to myIntVar,
        KEY_MY_INT_ARRAY to myIntArray,
        KEY_MY_STRING to myString
    )

CoroutineWorker

除了可以使用 Java 实现的 Worker 类 (Worker、ListenableWorker 和 RxWorker) 之外,还有唯一一个使用 Kotlin 协程实现的 Work 类——CoroutineWorker。

Worker 类与 CoroutineWorker 类的主要区别在于: CoroutineWorker 类的 doWork() 方法是一个可以执行异步任务的挂起函数,而 Worker 类的 doWork() 方法只能执行同步任务。CoroutineWorker 的另一个特性是可以自动处理任务的暂停和取消,而 Worker 类需要实现 onStopped() 方法来处理这些情况。

获得完整上下文信息,请参阅官方文档在 WorkManager 中进行线程处理。在这里,我想重点介绍一下什么是 CoroutineWorker,并且涵盖一些细小的但很重要的区别,以及深入了解如何使用在 WorkManager v2.1 中引入的新测试特性,来测试您的 CoroutineWorker 类。

正如前面写的那样,CoroutineWorker#doWork() 只是一个挂起函数。它默认是在 Dispatchers.Default 上启动的:


class MyWork(context: Context, params: WorkerParameters) :
        CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
return try {
            // 做点什么
            Result.success()
        } catch (error: Throwable) {
            Result.failure()
        }
    }
}

需要切记的是,这是使用 CoroutineWorker 代替 Worker 或 ListenableWorker 时的根本区别:

与 Worker 不同,此代码不会在 WorkManager 的 Configuration 中指定的 Executor 上运行。

正如刚才所说,CoroutineWorker#doWork() 默认是在 Dispatchers.Default 启动的。您可以使用 withContext() 对此配置进行自定义。


class MyWork(context: Context, params: WorkerParameters) :
        CoroutineWorker(context, params) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
return try {
            // 做点什么
            Result.success()
        } catch (error: Throwable) {
            Result.failure()
        }
    }
}

很少需要改变 CoroutineWorker 使用的 Dispatcher,因为 Dispatchers.Default 可以满足大多数情况下的需求。

要了解关于如何在 Kotlin 中使用 WorkManager,可以尝试这个 codelab。

总结

随着 WorkManager v2.1 以及 workManager-testing 中新特性的发布,CoroutineWorker 因其简单易用而大放光彩。现在您可以非常容易的对 Worker 类进行测试,并且 WorkManager 在 Kotlin 中的整体使用体验也非常棒。

如果您还没有在项目中使用 CoroutineWorker 以及 workmanager-runtime-ktx 中包含的其他扩展,强烈建议您在项目中使用它们。当使用 Kotlin 进行开发 (已经成为我的日常) 时,这是我使用 WorkManager 的首选方式。

希望这篇文章对您有所帮助,欢迎您在评论区积极留言,分享您在 WorkManager 使用中的见解或者问题。

WorkManager 相关资源

开发者指南 | 在 WorkManager 中进行线程处理 参考指南 | androidx.work Codelab | 使用 WorkManager 处理后台任务 WorkManager 的公开问题追踪器 发行日志 | WorkManager Stack Overflow 的 [android-workmanager] 标签 WorkManager 的源码 (AOSP的一部分)

收藏
评论区

相关推荐

WorkManager 在 Kotlin 中的实践
WorkManager 是一个 Android Jetpack 扩展库,它可以让您轻松规划那些可延后、异步但又需要可靠运行的任务。对于绝大部分后台执行任务来说,使用 WorkManager 是目前 Android 平台上的最佳实践。 WorkManager https://developer.android.google.cn/topic/libra
《前端算法系列》数组去重
虽然算法在前端开发中很少会得以使用,但是了解常用的算法,熟悉各种算法的性能和优劣,将会让你在前端的道路上走的更远。 前言 文中所有代码位于位于此代码仓库中(https://link.zhihu.com/?targethttps%3A//github.com/MrXujiang/dataAndMethods),大家可以下载代码进行学习、推敲和改进。
发现Kotlin一个神奇的bug
1、前言 本文将会通过具体的业务场景,由浅入深的引出Kotlin的一个bug,并告知大家这个bug的神奇之处,接着会带领大家去查找bug出现的原因,最后去规避这个bug。 2、bug复现 现实开发中,我们经常会有将Json字符串反序列化为一个对象问题,这里,我们用Gson来写一段反序列代码,如下: kotlin fun <T fromJson(js
GitHub最牛的Android开源项目,金三银四
Android目前也是非常成熟的,如今移动的变化也是比较大,不管是从Android系统本身的变化还是语言上,自从17年kotlin的作为第一语言,涉及到Android系统周边的非常之多内容,若全部自己去实现及掌握可能需要花费很多的精力,现在github中有很多非常优秀的项目,快速的学习及掌握; 1,视频播放器,基于IJKPlayer(兼容系统MediaPl
20 张图彻底弄懂 HTTPS 的原理
前言 近年来各大公司对信息安全传输越来越重视,也逐步把网站升级到 HTTPS 了,那么大家知道 HTTPS 的原理是怎样的吗,到底是它是如何确保信息安全传输的?网上挺多介绍 HTTPS,但我发现总是或多或少有些点有些遗漏,没有讲全,今天试图由浅入深地把 HTTPS 讲明白,相信大家看完一定能掌握 HTTPS 的原理,本文大纲如下: HTTP 为什么不安全
Ant Design 可编辑的树形表格
Ant Design Editable Tree TableAnt Design of React Editable Tree Table可编辑的树形表格Need in the work, but i did not find readymade components easy to understand after Baidu and Googl
Kotlin 协程中,关于 runBlocking, launch ,withContext ,async,doAsync 之间的简单区别
引入大佬的话,Kotlin的协程,本质上是一个线程框架,它可以方便的切换线程的上下文(如主线程切换到子线程/子线程切回主线程)。而平时我们要想在Android Studio使用协程,先要在gradle引入协程依赖: implementation "org.jetbrains.kotlinx:kotlinxcoroutinescore:1.3.3"
[concurrent-map]-并发map在go中的使用
关于我 通过学习和分享的过程,将自己工作中的问题和技术总结输出,希望菜鸟和老鸟都能通过自己的文章收获新的知识,并付诸实施。 引言Go语言原生的map类型并不支持并发读写。在Go 1.9之前,go语言标准库中并没有实现并发map。在Go 1.9中,引入了sync.Map。 concurrentmap的优势concurrentm
在微前端中,antd icon createFormIconfontCN 的本地化问题
首发于 <a name"tCbT2"</a 前言用过 antd icon 的朋友们可能知道,对于 createFormIconfontCN,其中介绍的用法是: 使用的是外链的方式javascriptimport { createFromIconfontCN } from '@antdesign/icons';const IconFon
CSReid库在NetCore工作场景中的使用
关于我过去 .net 最有名望的 ServiceStack.Redis 早已沦为商业用途,在 .NETCore 中使用只能充值。后来居上的 StackExchange.Redis 虽然能用,但是之前出现的各种Timeout错误也是让人很无语,所以也不作为使用的首选。经过网上的一些整理和推荐,发现了一款开源库CSReidsCore。CSRedisCore是国人
藏在Java随机数中的hello world
把229985452当做种子传入Random类,就可以得到hello,相应的147909649则能得到world。在Java中执行如下程序,它最终会打印输出hello world。 我很好奇这个种子数是谁找到的?以及这个027范围是怎么找到的? package person.xsc.datamanage;import java.util.Random;pu
前端vue中常用的插件
一.moment时间库 1.安装 npm install moment save2.在main.js中引入 import moment from 'moment'; //导入模块moment.locale('zhcn'); //设置语言 或 moment.lang('zhcn'); Vue.prototype.$moment moment;//赋值使用3.
go, iris , nuxt, 服务端渲染等技术在helloworld开发者社区中的应用与实践
大家好,helloworld.net 上线已经有近半年的时间了,转眼过的好快,在这半年的时间里,迭代了近10多个版本,优化了很多的体验,交互上的不足之处,同时也上线了我们的安卓 app, 苹果的因为还在申请开发者账号,所以暂时未上线在这半年的时间内,网友很给力,也给出了很多的建议和优化,也有不少网友说愿意为 helloworld开发者社区出一份力,在这里我感
https://cloud.tencent.com/developer/article/write/1830331
一、目标今天的目标是这个sign和appcode 二、步骤 Jadx没法上了app加了某梆的企业版,Jadx表示无能为力了。 FRIDADEXDumpDexDump出来,木有找到有效的信息。 Wallbreaker葫芦娃的Wallbreaker可以做些带壳分析,不过这个样本,用Frida的Spawn模式可以载入,Attach模式会失败。而直接用Objecti
Python中如何判断表的存在
MySQL如何判断表是否存在MySQL判断表是否存在可以使用下面语句:select from informationschema.tables where tablename 'student';select from informationschema.tables where tablename 'teacher';SQL语句说明:informati