Android - WorkManager

news/2024/4/26 6:49:16/文章来源:https://blog.csdn.net/m0_59482482/article/details/130263341

一、简介

1、WorkManager很适合用于处理一些要求定时执行的任务,它可以根据操作系统的版本自动选择 底层是使用AlarmManager实现还是JobScheduler实现,从而降低了我们的使用成本。另外, 它还支持周期性任务、链式任务处理等功能,是一个非常强大的工具。

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

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

dependencies {...implementation "androidx.work:work-runtime:2.2.0"
}

二、主要分为以下3步:

(1) 定义一个后台任务,并实现具体的任务逻辑;

(2) 配置该后台任务的运行条件和约束信息,并构建后台任务请求;

(3) 将该后台任务请求传入WorkManager的enqueue()方法中,系统会在合适的时间运行。

第一步要定义一个后台任务,这里创建一个SimpleWorker类,

/*** WorkManager*/
class SimpleWorker(context: Context,params:WorkerParameters):Worker(context,params){override fun doWork(): Result {Log.d("SimpleWorker", "do work in SimpleWorker")return Result.success()}}

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

doWork()方法不会运行在主线程当中,因此你可以放心地在这里执行耗时逻辑,不过这里简单 起见只是打印了一行日志。另外,doWork()方法要求返回一个Result对象,用于表示任务的 运行结果,成功就返回Result.success(),失败就返回Result.failure()。除此之外, 还有一个Result.retry()方法,它其实也代表着失败,只是可以结合 WorkRequest.Builder的setBackoffCriteria()方法来重新执行任务,我们稍后会进行 学习。

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

这一步其实也是最复杂的一步,因为可配置的内容非常多,不过目前我们还只是学习 WorkManager的基本用法,因此只进行最基本的配置就可以了,代码如下所示:

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

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

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

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

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

WorkManager.getInstance(context).enqueue(request)
class MainActivity : AppCompatActivity() {...override fun onCreate(savedInstanceState: Bundle?) {...doWorkBtn.setOnClickListener {val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()WorkManager.getInstance(this).enqueue(request)}}...
}

三、使用WorkManager处理复杂的任务

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

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

这就表示我们希望让SimpleWorker这个后台任务在5分钟后运行。你可以自由选择时间的单 位,毫秒、秒、分钟、小时、天都可以。 可以控制运行时间之后,我们再增加一些别的功能,比如说给后台任务请求添加标签:

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

那么添加了标签有什么好处呢?最主要的一个功能就是我们可以通过标签来取消后台任务请 求:

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

当然,即使没有标签,也可以通过id来取消后台任务请求

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

但是,使用id只能取消单个后台任务请求,而使用标签的话,则可以将同一标签名的所有后台任 务请求全部取消,这个功能在逻辑复杂的场景下尤其有用。 除此之外,我们也可以使用如下代码来一次性取消所有后台任务请求:

WorkManager.getInstance(this).cancelAllWork()

另外,我们在上一小节中讲到,如果后台任务的doWork()方法中返回了Result.retry(), 那么是可以结合setBackoffCriteria()方法来重新执行任务的,具体代码如下所示:

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)....setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS).build(

setBackoffCriteria()方法接收3个参数:第二个和第三个参数用于指定在多久之后重新执 行任务,时间最短不能少于10秒钟;第一个参数则用于指定如果任务再次执行失败,下次重试 的时间应该以什么样的形式延迟。这其实很好理解,假如任务一直执行失败,不断地重新执行 似乎并没有什么意义,只会徒增设备的性能消耗。而随着失败次数的增多,下次重试的时间也 应该进行适当的延迟,这才是更加合理的机制。第一个参数的可选值有两种,分别是LINEAR和 EXPONENTIAL,前者代表下次重试时间以线性的方式延迟,后者代表下次重试时间以指数的方 式延迟。

了解了Result.retry()的作用之后,你一定还想知道,doWork()方法中返回 Result.success()和Result.failure()又有什么作用?这两个返回值其实就是用于通知 任务运行结果的,我们可以使用如下代码对后台任务的运行结果进行监听:

WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).observe(this) { workInfo ->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")}}

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

接下来,我们再来看一下WorkManager中比较有特色的一个功能——链式任务。

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

val sync = ...
val compress = ...
val upload = ...
WorkManager.getInstance(this).beginWith(sync).then(compress).then(upload).enqueue()

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

。前面所介绍的WorkManager的所有功能,在国产手机上都有 可能得不到正确的运行。这是因为绝大多数的国产手机厂商在进行Android系统定制的时候会增 加一个一键关闭的功能,允许用户一键杀死所有非白名单的应用程序。而被杀死的应用程序既 无法接收广播,也无法运行WorkManager的后台任务。这个功能虽然与Android原生系统的设 计理念并不相符,但是我们也没有什么解决办法。或许就是因为有太多恶意应用总是想要无限 占用后台,国产手机厂商才增加了这个功能吧。因此,这里给你的建议就是,WorkManager可 以用,但是千万别依赖它去实现什么核心功能,因为它在国产手机上可能会非常不稳定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_102424.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bugku——应急加固1

来打一下bugku的应急加固靶场,靶场链接:https://ctf.bugku.com/ctfplus/detail/id/2.html 启动环境 1、JS劫持域名 直接访问ip地址,发现是xxx学院二手交易市场,随后被劫持跳转到了一个博客页面。 博客地址就是第一个flag&…

Android音视频开发-OpenGL ES正交投影实现方法

本文实例为大家分享了OpenGL ES正交投影展示的具体代码,供大家参考,具体内容如下 绘制正方形 在最开始绘制的六边形里面好像看起来挺容易的,也没有出现什么问题,接下来不妨忘记前面绘制六边形的代码,让我们按照自己的…

Ubuntu下打开QtCreator,环境变量(PATH、LD_LIBRARY_PATH等)与预期不一致的问题

现象展示 在Ubuntu中,安装好Qt之后,可以在系统桌面的左下角找到启动图标 但是,这种方式启动的QtCreator所读取到的环境变量和我们从命令行读取到的不一致: 可以看到,明显少了这个:/opt/ros/humble/bin 因…

很合适新手入门使用的Python游戏开发包pygame实例教程-02[如何控制飞行]

前面一篇博文,我们让飞机动起来了,但不是那么完美,我们继续来完善我们的游戏代码,本篇博文主要介绍获取按键的方式已经飞行的控制。 文章目录 一、获取按键的三种方式1、通过event.get配合pygame.key枚举2、通过event.get配合ord…

微积分入门

文章目录 前言初期积分微分微积分问题 后期极限 ε \varepsilon ε- δ \delta δ极限勒贝格积分 结语 前言 微积分总共走过了两个时期。首先是牛顿和莱布尼茨利用无穷小量定义微分和积分,并且发现了微分和积分的关系,这是第一个时期,这时的…

设计模式——组件协作模式之模板方法模式

文章目录 前言一、“组件协作” 模式二、模板方法模式1、动机2、源码分析讲解①、结构化软件设计②、面向对象软件设计 三、模板方法模式定义四、结构要点总结 前言 一、“组件协作” 模式 现代软件专业分工之后的第一个结果是 “框架与应用程序的划分”,“组件协作…

Cuckoo Filter

其他判重数据结构 Bloom Filter 无法支持删除和计数的功能,需要更多的存储空间来存储数据 因为在CS中,删除和计数是常见的操作,但是这会对布隆过滤器的存储空间产生影响,同样为了实现这一操作,需要更多的存储空间 数…

ArcGIS Pro导航工具

主要导航工具为浏览工具 、屏幕导航器 、书签 、转到XY工具 。 其它还包括链接视图、地图比例(2D)、场景高度(3D)、暂停并刷新绘制、照相机属性、在3D模式下导航、键盘快捷键等。 1 主要导航工具 地图和场景的默认工具为浏览工具…

C++ “类与对象”

类与对象的概念 类相当于是结构体的声明,是结构体的设计图,而对象是利用设计图的创造的产物. (1).类的大小计算 类的大小计算时与结构体类似,但函数是不计入大小的(函数放在单独的公共空间). 在…

Unity API详解——Object类

Object类是Unity中所有对象的基类,例如GameObject、Component、Material、Shader、Texture、Mesh、Font等都是Object的子类。本博客介绍Object类的一些实例方法和静态方法。 一、Object类实例方法 在Object类中,涉及的实例方法主要有GetInstanceID方法…

8. 优先队列

8. 优先队列 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在某些情况下,我们可能需要找出队列中的最大值或者最小值,例如使用一个队列保存计算机的任务,一般情况下计算机的任务都是有优先级…

ROS1学习笔记:常用可视化工具的使用(ubuntu20.04)

参考B站古月居ROS入门21讲:常用可视化工具的实现 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录 一、日志输出工具:rqt_console二、绘制数据曲线:rqt_plot三、 图像渲染工具:rqt_image_view四、图形界面总接口:r…

kong(4):限流配置

Kong 提供了 Rate Limiting 插件,实现对请求的限流功能,避免过大的请求量过大,将后端服务打挂。 Rate Limiting 支持秒/分/小时/日/月/年多种时间维度的限流,并且可以组合使用。例如说:限制每秒最 多 100 次请求&…

初识Android内存优化

一、简介 Android 内存优化是指优化 Android 应用程序的内存使用,以减少可用内存的消耗,提高应用程序的性能和可靠性。Android 内存优化可以通过减少内存使用量,减少对资源的消耗,以及提高内存利用率来实现。 安卓系统对每个应用…

什么才是好CDN

选择一种领先于网络和移动技术不断进步以及不断演变的威胁格局的CDN,将使您能够始终如一地为客户提供尽可能好的在线体验,同时最大限度地降低运营复杂性和管理成本。 但问题来了:什么才是最好的CDN? 这个问题的唯一答案是&#x…

Tomcat概述以及部署与优化

一、Tomcat概述 1、Tomcat的概念 Tomcat是Java语言开发的,服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选。一般来说&am…

Flutter开发日常练习-小猫咪杂货店(新增动画和跳转抖音)

之前的练习加了个详情页面,然后跳转第三方页面抖音用户详情页面 跳转详情页添加了Hero的动画,共享元素过度 一个 标准 hero 动画 使 hero 从一页飞至新页面,通常以不同大小到达不同的目的地。 设定好每个图片的id,通过id作为 Hero 组件的标识,id不能重,否则会报错&…

OSCP-Medjed(重置用户密码、mysql写webshell、可写文件替换提权)

目录 扫描 FTP WEB 提权 扫描 FTP 尝试登录到FTP服务器,该服务器位于端口30021 使用Filezilla,并能够浏览文件。那里有一些配置文件,但找不到任何值得注意的东西,不能写入目录。

算法--前缀和技巧 (蓝桥杯123-灵能传输)

文章目录 什么是前缀和用途什么时候用例题[蓝桥杯 2021 国 ABC] 123题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路代码 灵能传输(蓝桥杯96%,洛谷ac)[蓝桥杯 2019 省 B] 灵能传输题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1…

【Leetcode -21.合并两个有序链表 -83.删除排序链表中的重复元素】

Leetcode Leetcode-21.合并两个有序链表Leetcode-83.删除排序链表中的重复元素 Leetcode-21.合并两个有序链表 题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 […