定期工作请求是否应该立即执行?

问题描述 投票:0回答:3

编辑(TL;DR)

我没有意识到有多个构造函数用于定期工作请求。我感到困惑的线索是在已接受答案的评论中。

背景

我在安排工作时试图解决一些特殊情况。其中之一涉及立即开展工作,然后创建定期工作请求。我在 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 DO NOT 立即执行工作。 Android 文档应该说:

该工作会执行多次,直到被取消,第一个周期立即开始。如果满足约束,则第一个工作执行会在第一个弹性间隔内发生。

问题

我的结论看起来合理吗?还有什么我没有考虑到的吗?

android android-workmanager
3个回答
2
投票

你想多了。请转储JS:

https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging

使用adb shell dumpsys jobscheduler

只需检查转储中哪些是未满足的约束:

  Required constraints: TIMING_DELAY CONNECTIVITY [0x90000000]
  Satisfied constraints: DEVICE_NOT_DOZING BACKGROUND_NOT_RESTRICTED WITHIN_QUOTA [0x3400000]
  Unsatisfied constraints: TIMING_DELAY CONNECTIVITY [0x90000000]

还有:

Minimum latency: +1h29m59s687ms

1
投票

据我了解这个构造函数:

          PeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, 
    long repeatInterval, TimeUnit repeatIntervalTimeUnit,
 long flexInterval, TimeUnit flexIntervalTimeUnit)

意味着你的工作将在

flexInterval
repeatInterval

内执行

0
投票

默认情况下,定期工作请求会立即运行。您可以使用

在构建器中更改此设置

.setInitialDelay(Duration)
.

如果您查看构建器的代码,您可以看到默认的

initialDelay
值为
0

© www.soinside.com 2019 - 2024. All rights reserved.