Android Jetpack组件之WorkManager后台任务管理的介绍与使用(一)
创始人
2024-05-24 13:13:24
0

一、介绍

Jetpack?

        我们经常看到,似乎很高端,其实这个就是一个名词,或者说是一种框架概念。

Jetpack 包含一系列 Android 库,它们都采用最佳做法并在 Android 应用中提供向后兼容性。

Jetpack 应用架构指南概述了构建 Android 应用时要考虑的最佳做法和推荐架构。

最终就是Android平台的一个介绍,有些新人看到又以为是什么平台,甚至一些招聘会写需要了解Room数据,Jetpack组件,其实我们现在好多已在使用了,但是非专业人会不停提jetpack导致一些人在理解的时候被吓到了。

JetPack组件已全部支出androidX,如果你的项目没有升级到AndroidX,请先升级到AdnroidX。

利用 Jetpack

Jetpack 库可以单独使用,也可以组合使用,以满足应用的不同需求。

  • WorkManager - 满足您的后台调度需求。
  • Room - 实现数据存储持久性。
  • Navigation - 管理应用导航流程。
  • CameraX - 满足相机应用需求。
  • 请参阅所有 Jetpack 库的概览。

二、WorkManager

        WorkManager 是适合用于持久性工作的推荐解决方案。如果工作始终要通过应用重启和系统重新启动来调度,便是持久性的工作。由于大多数后台处理操作都是通过持久性工作完成的,因此 WorkManager 是适用于后台处理操作的主要推荐 API。

持久性工作的类型

WorkManager 可处理三种类型的持久性工作:

  • 立即执行:必须立即开始且很快就完成的任务,可以加急。
  • 长时间运行:运行时间可能较长(有可能超过 10 分钟)的任务。
  • 可延期执行:延期开始并且可以定期运行的预定任务。
持久性工作的类型

 

类型周期使用方式
立即一次性OneTimeWorkRequest 和 Worker

如需处理加急工作,请对 OneTimeWorkRequest 调用 setExpedited()

长期运行一次性或定期任意 WorkRequest 或 Worker。在工作器中调用 setForeground() 来处理通知。
可延期一次性或定期PeriodicWorkRequest 和 Worker

使用 WorkManager 保证工作可靠性

WorkManager 适用于需要可靠运行的工作,即使用户导航离开屏幕、退出应用或重启设备也不影响工作的执行。例如:

  • 向后端服务发送日志或分析数据。
  • 定期将应用数据与服务器同步。

WorkManager 不适用于那些可在应用进程结束时安全终止的进程内后台工作。它也并非对所有需要立即执行的工作都适用的通用解决方

三、接入

1、依赖库

//work
def  work_version = "2.7.1"// (Java only)
implementation("androidx.work:work-runtime:$work_version")// Kotlin + coroutines
implementation("androidx.work:work-runtime-ktx:$work_version")// optional - RxJava2 support
implementation("androidx.work:work-rxjava2:$work_version")// optional - GCMNetworkManager support
implementation("androidx.work:work-gcm:$work_version")// optional - Multiprocess support
implementation "androidx.work:work-multiprocess:$work_version"

由于国内应用,GCM可以不需要,因为这个GCM是google service,国内的手机不支持

2、接入

2.1 先定义一个worker

工作使用 Worker 类定义。doWork() 方法在 WorkManager 提供的后台线程上异步运行

class MyWorks(context: Context,workerParameters: WorkerParameters) : Worker(context, workerParameters) {@SuppressLint("RestrictedApi")override fun doWork(): Result {//后台异步执行var success=Result.Success()var error=Result.failure()var retry=Result.retry()return success}
}

doWokr():是我们需要执行的方法体,需要异步执行,都将在这边执行。最后将执行的结果返回即可Result。

从 doWork() 返回的 Result 会通知 WorkManager 服务工作是否成功,以及工作失败时是否应重试工作。

  • Result.success():工作成功完成。
  • Result.failure():工作失败。
  • Result.retry():工作失败,应根据其重试在其他时间尝试。
public Success(@NonNull Data outputData) {super();mOutputData = outputData;
}

创建 WorkRequest

        定义工作后,必须使用 WorkManager 服务进行调度该工作才能运行。对于如何调度工作,WorkManager 提供了很大的灵活性。您可以将其安排为在某段时间内定期运行,也可以将其安排为仅运行一次。

        不论您选择以何种方式调度工作,请始终使用 WorkRequest。Worker 定义工作单元,WorkRequest(及其子类)则定义工作运行方式和时间。在最简单的情况下,您可以使用 OneTimeWorkRequest

提交work执行:

val workRequest:WorkRequest=OneTimeWorkRequestBuilder().build()
WorkManager.getInstance(application).enqueue(workRequest)

这种是一次性调度。

也可以通过from来创建request:

val workRequest=  OneTimeWorkRequest.from(MyWorks::class.java)

这种构建也只能构建简单的

复杂构建:

复杂的构建需要通过OneTimeWorkRequestBuilder来构建

val build=OneTimeWorkRequestBuilder()
通过build来设置加载机制和延迟等

调度加急

        WorkManager 2.7.0 引入了加急工作的概念。这使 WorkManager 能够执行重要工作,同时使系统能够更好地控制对资源的访问权限。

加急工作具有以下特征:

  • 重要性:加急工作适用于对用户很重要或由用户启动的任务。
  • 速度:加急工作最适合那些立即启动并在几分钟内完成的简短任务。
  • 配额:限制前台执行时间的系统级配额决定了加急作业是否可以启动。
  • 电源管理:电源管理限制(如省电模式和低电耗模式)不太可能影响加急工作。
  • 延迟时间:系统立即执行加急工作,前提是系统的当前工作负载允许执行此操作。这意味着这些工作对延迟时间较为敏感,不能安排到以后执行。

执行加急

从 WorkManager 2.7 开始,您的应用可以调用 setExpedited() 来声明 WorkRequest 应该使用加急作业,以尽可能快的速度运行。以下代码段展示了关于如何使用 setExpedited() 的示例

val request = OneTimeWorkRequestBuilder().setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST).build()

向后兼容性和前台服务

为了保持加急作业的向后兼容性,WorkManager 可能会在 Android 12 之前版本的平台上运行前台服务。前台服务可以向用户显示通知。

在 Android 12 之前,工作器中的 getForegroundInfoAsync() 和 getForegroundInfo() 方法可让 WorkManager 在您调用 setExpedited() 时显示通知。

如果您想要请求任务作为加急作业运行,则所有的 ListenableWorker 都必须实现 getForegroundInfo 方法

override fun getForegroundInfoAsync(): ListenableFuture {return super.getForegroundInfoAsync()
}

CoroutineWorker:

        如果您使用 CoroutineWorker,则必须实现 getForegroundInfo()。然后,在 doWork() 内将其传递给 setForeground()。这样做会在 Android 12 之前的版本中创建通知

    override suspend fun getForegroundInfo(): ForegroundInfo {val id = Random.nextInt(0, Int.MAX_VALUE)return ForegroundInfo(id, getNotion())}private fun getNotion(): Notification {val notification = Notification()return notification;}

配额政策:

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST:
           这会导致作业作为普通工作请求运行。上述代码段演示了此操作。
     
  • OutOfQuotaPolicy.DROP_WORK_REQUEST
    这会在配额不足时导致请求取消。

定期调度

您的应用有时可能需要定期运行某些工作,使用 PeriodicWorkRequest 创建定期执行的 WorkRequest

val request=PeriodicWorkRequestBuilder(5,TimeUnit.MILLISECONDS)

解释:

        时间间隔定义为两次重复执行之间的最短时间。工作器的确切执行时间取决于您在 WorkRequest 对象中设置的约束以及系统执行的优化。

val reques1=PeriodicWorkRequestBuilder(5,TimeUnit.HOURS,15,TimeUnit.MINUTES)

重复间隔必须大于或等于 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,而灵活间隔必须大于或等于 PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS

    /*** The minimum interval duration for {@link PeriodicWorkRequest} (in milliseconds).*/@SuppressLint("MinMaxConstant")public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes./*** The minimum flex duration for {@link PeriodicWorkRequest} (in milliseconds).*/@SuppressLint("MinMaxConstant")public static final long MIN_PERIODIC_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes.

repeatInterval :重复的时间值
flexInterval:第二个时间值,

约束

约束可确保将工作延迟到满足最佳条件时运行。以下约束适用于 WorkManager

NetworkType约束运行工作所需的网络类型。例如 Wi-Fi (UNMETERED)。
BatteryNotLow如果设置为 true,那么当设备处于“电量不足模式”时,工作不会运行。
RequiresCharging如果设置为 true,那么工作只能在设备充电时运行。
DeviceIdle如果设置为 true,则要求用户的设备必须处于空闲状态,才能运行工作。在运行批量操作时,此约束会非常有用;若是不用此约束,批量操作可能会降低用户设备上正在积极运行的其他应用的性能。
StorageNotLow

如果设置为 true,那么当用户设备上的存储空间不足时,工作不会运行。

如需创建一组约束并将其与某项工作相关联,请使用一个 Contraints.Builder() 创建 Constraints 实例,并将该实例分配给 WorkRequest.Builder()

       val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).setRequiresCharging(true).build()val myWorkRequest: WorkRequest =OneTimeWorkRequestBuilder().setConstraints(constraints).build()

如果指定了多个约束,工作将仅在满足所有约束时才会运行。

如果在工作运行时不再满足某个约束,WorkManager 将停止工作器。系统将在满足所有约束后重试工作。

延迟:

如果您不希望工作立即运行,可以将工作指定为在经过一段最短初始延迟时间后再启动

al myWorkRequest = OneTimeWorkRequestBuilder().setInitialDelay(10, TimeUnit.MINUTES).build()

这个延迟和handler的延迟机制是一样使用。PeriodicWorkRequest 设置初始延迟时间,在这种情况下,定期工作只有首次运行时会延迟。

重试和退避

如果您需要让 WorkManager 重试工作,可以从工作器返回 Result.retry()。然后,系统将根据退避延迟时间和退避政策重新调度工作。

  • 退避延迟时间指定了首次尝试后重试工作前的最短等待时间。此值不能超过 10 秒(或 MIN_BACKOFF_MILLIS)。

  • 退避政策定义了在后续重试过程中,退避延迟时间随时间以怎样的方式增长。WorkManager 支持 2 个退避政策,即 LINEAR 和 EXPONENTIAL

val myWorkRequest = OneTimeWorkRequestBuilder().setBackoffCriteria(BackoffPolicy.LINEAR,OneTimeWorkRequest.MIN_BACKOFF_MILLIS,TimeUnit.MILLISECONDS).build()

最短退避延迟时间设置为允许的最小值,即 10 秒。由于政策为 LINEAR,每次尝试重试时,重试间隔都会增加约 10 秒。例如,第一次运行以 Result.retry() 结束并在 10 秒后重试;然后,如果工作在后续尝试后继续返回 Result.retry(),那么接下来会在 20 秒、30 秒、40 秒后重试,以此类推。如果退避政策设置为 EXPONENTIAL,那么重试时长序列将接近 20、40、80 秒,以此类推。

标记

在request的对象中,都支持setTag,方便我们在获取对象时,可以通标记值来获取。这个类似线程池获取某个线程一样,只要我们知道线程的名字,就能准确的找到

val myWorkRequest = OneTimeWorkRequestBuilder().addTag("cleanup").build()

数据绑定:

在处理异步操作时,必然和数据打交道,如何传递数据呢?通过Data来传递

通过request的setInputData来完成,我们在override fun doWork(): Result{}中,获取到

override fun doWork(): Result {//数据集合var data= inputData;return retry
}

同样,也可以将结果通过Resukt返回出去。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...