首页 > 解决方案 > 定期工作请求是否应该立即执行?

问题描述

编辑(TL;DR)

我没有意识到定期工作请求的构造函数不止一个。我困惑的线索在接受答案的评论中。

背景

我在安排工作时尝试解决一些特殊情况。其中之一涉及立即工作,然后创建定期工作请求。我在 Android 的PeriodicWorkRequest 文档中发现了这一点:

这项工作会执行多次,直到被取消,第一次执行会立即发生,或者一旦满足给定的约束就会发生。

我认为这意味着工作将在创建请求时执行。但是,这不是我的测试实现中发生的事情。(对于这项工作,不需要 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 文档应该改为:

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

问题

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

标签: androidandroid-workmanager

解决方案


你想多了。请转储JS:

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

使用adb shell dumpsys 作业调度程序

只需检查转储中的 Unsatisfied 约束是什么:

  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

推荐阅读