【发布时间】:2021-08-31 14:07:40
【问题描述】:
编辑(TL;DR)
我没有意识到周期性工作请求的构造函数不止一个。我的困惑的线索是在接受答案的 cmets 中。
背景
我在安排工作时尝试解决一些特殊情况。其中之一涉及立即工作,然后创建定期工作请求。我在 Android 的 PeriodicWorkRequest documentation:
中找到了这个这项工作会执行多次,直到它被取消,第一次执行会立即发生,或者一旦满足给定的约束就会发生。
我认为这意味着工作将在创建请求时执行。但是,这不是我的测试实现中发生的事情。 (对于这项工作,不需要 CoroutineWorker 或网络连接限制,但它适用于我的业务需求,因此我正在对其进行测试)
起始工人
object WorkerManager {
private val TAG = "WORKER_MANAGER_TEST"
fun buildWorkRequest(
startingNumber: Int,
context: Context
) {
val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val workRequest = PeriodicWorkRequest.Builder(
PeriodicWorker::class.java,
1,
TimeUnit.HOURS,
15,
TimeUnit.MINUTES
)
.setInputData(
workDataOf(Constants.INPUT_DATA_NUMBER to startingNumber)
)
.addTag(Constants.PERIODIC_WORKER_TAG)
.setConstraints(constraints)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
Constants.PERIODIC_WORKER_NAME,
ExistingPeriodicWorkPolicy.REPLACE,
workRequest
)
Log.d(TAG, "Worker started. Starting number: $startingNumber")
}
}
工人:
class PeriodicWorker(context: Context, workerParams: WorkerParameters): CoroutineWorker(context,
workerParams
) {
companion object {
var isInit = false
var count: Int = 1
}
override suspend fun doWork(): Result = try {
if (!isInit) {
count = inputData.getInt(Constants.INPUT_DATA_NUMBER, Constants.DEFAULT_DATA_NUMBER)
isInit = true
} else {
count += 1
}
Repository.updateNumber(count)
Result.success()
} catch (exception: Exception) {
Result.failure()
}
}
回购:
object Repository {
private val TAG = "REPOSITORY_TAG"
private val _number = MutableStateFlow(0)
val number: StateFlow<Int> = _number
suspend fun updateNumber(number: Int) {
Log.d(TAG, "Number updated to: $number")
_number.emit(number)
}
}
视图模型:
class NumberViewModel : ViewModel() {
private val _count = MutableLiveData(0)
val count: LiveData<Int> = _count
init {
viewModelScope.launch {
Repository.number.collect {
_count.postValue(it)
}
}
}
}
结果
我以 10 作为起始编号启动了一个工人。
日志:
8:45am - Worker started. Starting number: 10
9:37am - Number updated to: 10 // work executed
10:37am - Number updated to: 11 // work executed
11:37am - Number updated to: 12 // work executed
设备信息
操作系统版本 28 -- 三星 SM-T390
我的结论
约束 - 不能成为问题。在上述测试期间我有网络连接,这是唯一给定的限制。
电池优化 - 我确信此应用在运行此测试之前已被列入白名单。
总之,PeriodicWorkRequests 不要立即执行工作。 Android 文档应该改为:
这项工作会执行多次,直到被取消,第一阶段立即开始。在满足约束的情况下,第一个工作执行将在第一个弹性间隔内发生。
问题
我的结论看起来合理吗?有什么我没有考虑到的吗?
【问题讨论】:
-
有趣的是,
updateNumber第一次在上午 9 点 37 分被调用,number的值是 11,所以count已经递增了。这应该意味着else分支已被占用,因此工作人员应该已经执行过一次。我不明白为什么它没有出现在日志中。 -
我很抱歉。我手动编写了这些日志,它们是错误的。感谢那!我将它们更新为它们实际出现的方式。
-
答案在你的请求构造函数中
-
@Alex Rmcf 的意思是:在请求构造函数中声明的 repeatInterval 也被认为是在初始执行之前必须满足的约束。
-
英语不是我最好的技能)
标签: android android-workmanager