在Android中,一般我们写一个需要后台执行的任务时,比如网络请求,蓝牙操作等,都会使用Service。但现在WorkManager有逐渐替代Service的趋势,一方面WorkManager有其独特优势,再一个Service写起来确实麻烦些。
WorkManager概述
WorkManager大概有以下几个优点:
- 可靠性:保证任务最终会被执行,即使应用退出或设备重启。
- 电池效率:自动选择最佳的时间和方式来运行任务,以减少对电池的影响。
- 简洁性:相比传统的后台服务,提供了更简单的 API。
- 灵活性:支持一次性任务和周期性任务,以及任务间的依赖关系。
- 适应性:可以设置任务的约束条件,如网络连接、充电状态等。
- 兼容性好:可以在所有版本的 Android 上正常工作。
也就是说,WorkManager能更好适应手机环境,兼具效率基础上最大限度保证任务可靠执行。当然,凡事有两面性,提高效率和可靠性的代价就是即时性可能会受点影响,WorkManager的缺点总结如下:
- 延迟执行:可能不如直接启动服务或线程来得即时。
- 学习曲线:对于习惯了传统服务的开发者来说,可能需要时间适应。
- 功能限制:不能实时监听任务进度或结果,只能监听任务状态变化。
- 性能:可能会增加应用程序的内存和 CPU 占用。
- 电池消耗:频繁执行后台任务可能会导致电池消耗增加。
- 资源调度:不能保证任务会在特定时间内开始执行。
我们需要根据使用场景来合理判断,一般来说,WorkManager可以应用在以下场景:
- 数据同步:定期将本地数据与服务器进行同步。
- 定时任务:例如定时清理缓存等。
- 后台上传下载:例如下载应用更新、下载图片等。
- 报告统计:定时发送统计数据至服务器。
- 通知推送:在特定时间发送本地或远程通知
WorkManager的集成使用
我们以网络请求为例,简单看下WorkManager的使用。
首先我们项目使用了Jetpack Compose框架,以依赖注入的方式操作WorkManager实例。
class SyncWorkerManager @Inject constructor(
@ApplicationContext private val context: Context,
) {
private val SYNC_WORK_NAME = "SyncWorkerName";
fun sync() {
val workManager = WorkManager.getInstance(context)
workManager.enqueueUniqueWork(
SYNC_WORK_NAME,
ExistingWorkPolicy.KEEP,
SyncWorker.workRequest()
)
}
}
这里我们定义了同步网络数据的接口,这个接口实际就是启动一个Worker,下面来看一下Worker的具体代码
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted private val appContext: Context,
@Assisted workerParams: WorkerParameters,
private val networkRepository: NetworkRepository,
private val dataRepository: DataRepository
) : CoroutineWorker(appContext, workerParams) {
@SuppressLint("MissingPermission")
override suspend fun doWork(): Result = withContext(IO) {
val dataList = networkRepository.getData()
val dataListIds = dataList.map { it.id }
if (dataList.isNotEmpty()) {
// merge
val dataDB = dataRepository.getDataList()
val dataDBIds = dataDB.map { it.uid }
val toIgnore = dataListIds.intersect(dataDBIds)
val toAdd = dataListIds.subtract(dataDBIds)
val toDelete = dataDBIds.subtract(dataListIds)
if (toAdd.isNotEmpty()) {
dataRepository.add(dataList.filter { toAdd.contains(it.id) }.map { it.toDataDB() })
}
if (toDelete.isNotEmpty()) {
dataRepository.delete(toDelete)
}
}
Result.success()
}
companion object {
fun workRequest() = OneTimeWorkRequestBuilder<SyncWorker>()
.build()
}
}
这里的代码也很好理解,就是做一个网络请求,然后和本地数据库room里的数据进行merge。可以说是十分常见的一个使用场景了。
调用的话,SyncWorkerManager可以在viewModel中直接引入,封装出接口进行调用,像下面代码片段这样
@HiltViewModel
class MyViewModel @Inject constructor(
val myRepository: MyRepository,
val syncWorkerManager: SyncWorkerManager
) : ViewModel() {
fun sync() {
syncWorkerManager.sync()
}
}
以上就是WorkManager的使用,还是很简单方便的,如果有替代Service的想法,不妨尝试一下。
本文暂时没有评论,来添加一个吧(●'◡'●)