序言
本文主要讲WorkManager的一些使用
WorkManager是在 Android 应用中调度和执行后台任务。它提供了一种灵活、可靠的方式来管理后台任务,并确保它们在最佳的设备条件下执行。
以下是 WorkManager 的主要作用:
后台任务调度:WorkManager 允许您调度延迟执行或周期性执行的后台任务。您可以指定任务的触发条件,例如设备空闲时、电量充足时或网络连接可用时。这使得您可以在适当的时机执行任务,以避免对设备性能和用户体验造成影响。
灵活的执行策略:WorkManager 提供了多种执行策略,以适应不同的需求。它可以在设备闲置时执行任务,也可以在指定的时间间隔内重复执行任务。此外,WorkManager 还具有智能的退避和重试功能,可以自动处理任务执行失败的情况。
设备适配性:WorkManager 能够与不同版本的 Android 平台和设备进行适配。它会自动选择合适的后台执行解决方案,如 JobScheduler(Android 5.0 及以上)或 AlarmManager(Android 4.4 及以下),以确保任务能够在各种设备上正常运行。
生命周期感知性:WorkManager 可以与应用程序的生命周期进行集成,因此即使应用程序在后台运行或在设备重启后重新启动,它也可以继续执行任务。这使得您的任务能够持久地在设备上运行,并保持与应用程序的一致性。
跨应用程序支持:WorkManager 可以在多个应用程序之间共享和传递数据,使不同应用程序之间的后台任务协同工作成为可能。这对于需要在不同应用程序之间进行数据同步或协作的情况非常有用。
使用方式
引入依赖
implementation "androidx.work:work-runtime:2.7.1"
//此依赖可以在WorkManager里面使用协程
implementation 'androidx.work:work-runtime-ktx:2.7.1'
创建 Worker 类
需要创建一个继承自 Worker 的工作类,用于定义要在后台执行的任务。例如,创建一个名为 MyWorker.java 的文件,并实现 doWork() 方法:
public class MyWorker extends Worker {public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {super(context, workerParams);}@NonNull@Overridepublic Result doWork() {// 在这里执行后台任务逻辑// ...// 返回 Result.success()、Result.failure() 或 Result.retry()return Result.success();}
}
这个是一般的使用方式,但是如果想要在WorkManager里面使用协程的话,需要这样创建,我们这里创建一个UploadWorker类
class UploadWorker(context: Context, workerParameters: WorkerParameters) :CoroutineWorker(context, workerParameters) {override suspend fun doWork(): Result {return withContext(Dispatchers.IO) {Result.success()}}
我们创建一个WorkManager
我是在Service
里面创建的
//懒加载private val workManager: WorkManager by lazy {WorkManager.getInstance(this)}
//清删除已完成的、取消的或失败的后台任务。它是一个方法来清理 WorkManager 的任务队列,以便只保留有效的任务信息。//workManager.pruneWork()//在什么状态下执行val constraints = Constraints.Builder().setRequiresCharging(true) // 需要充电状态.setRequiredNetworkType(NetworkType.CONNECTED) // 需要网络连接.build()var workInfoList: MutableList<WorkInfo>? = nulltry {//获取带有某个TAG的WorkManagerworkInfoList =workManager.getWorkInfosByTag(ConfigData.STR_WORK_MANAGER_NAME).get()} catch (e: java.lang.Exception) {e.printStackTrace()}if (workInfoList.isNullOrEmpty()) {Log.e(TAG, "此时WorkManager里面没有任务")//设置15分钟执行一次的循环任务(循环任务最低就是15分钟)val request =PeriodicWorkRequest.Builder(UploadWorker::class.java, 15, TimeUnit.MINUTES).setInitialDelay(1, TimeUnit.MINUTES)//首次执行延迟1分钟执行.addTag(ConfigData.STR_WORK_MANAGER_NAME)//添加TAG.setConstraints(constraints).build()Log.e(TAG, "开始执行定时循环任务")workManager.enqueue(request)} else {//Log.e(TAG, "此时运行的WorkManager服务:$workInfoList")for (info in workInfoList) {Log.e(TAG, "此时运行的WorkManager服务ID:${info.id}")Log.e(TAG, "此时运行的WorkManager服务TAG:${info.tags}")Log.e(TAG, "此时运行的WorkManager服务STATE:${info.state}")Log.e(TAG, "此时运行的WorkManager服务OUTPUTDATA:${info.outputData}")Log.e(TAG, "此时运行的WorkManager服务PROGRESS:${info.progress}")Log.e(TAG, "此时运行的WorkManager服务ATTEMPT:${info.runAttemptCount}")}}
如果不想要WorkManager,可以使用以下方式进行取消
取消单个任务:
可以使用 WorkManager 的 cancelWorkById(UUID) 方法取消具有指定唯一标识符的单个任务。传入任务的唯一标识符即可取消该任务。
val workId: UUID = // 获取要取消任务的唯一标识符
WorkManager.getInstance(context).cancelWorkById(workId)
取消带有特定标签的任务:
如果给任务设置了标签,可以使用 WorkManager 的 cancelAllWorkByTag(String) 方法取消所有具有特定标签的任务。传入任务的标签名称即可取消带有该标签的所有任务。
val tag: String = // 获取要取消任务的标签名称
WorkManager.getInstance(context).cancelAllWorkByTag(tag)
注意:取消任务时,只会取消还未开始执行的任务。如果任务已经在运行或已经完成,取消操作将不会产生任何影响。
取消所有任务:
如果想取消所有当前排队的任务,可以使用 WorkManager 的 cancelAllWork() 方法。
WorkManager.getInstance(context).cancelAllWork()
注意
我们在创建这个WorkManager之后,WorkManager会自动在后台进行运行,即使我们的APP程序已经停止运行了,我们创建的WorkManager还是会继续运行,此问题需要我们注意。
比如我们在我们的APP程序启动运行后自动创建一个WorkManager
执行任务,此时我们给这个WorkManager添加了一个TAG
,但是我们在APP结束运行之后,我们的WorkManager还在运行
,然后我们再启动APP,此时又创建了一个新的WorkManager
,然后根据程序代码,我们给这个WorkManager又赋值一个相同的TAG
,是的,不同的WorkManager是可以有相同的TAG
的,因为他们的id是不一样的
,所以他们不是同一个WorkManager
。