workmanager listener called immediately
Asked Answered
B

2

7

I need to have a callback upon Work completion from WorkManager (android.arch.work:work-runtime-ktx:1.0.0-alpha11). Yet the listener I'm adding is called immediately after work is scheduled.

Here's what I do:

val work = OneTimeWorkRequestBuilder<UploadWorker>()
                .setConstraints(constraints)
                .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
                .setInputData(inputData)
                .build()
workManager.beginUniqueWork(INSURANCE_UPLOAD_WORKER, ExistingWorkPolicy.REPLACE, work)
                .enqueue().result.toWorkResult()

The UploadWorker class returns Success only after completing the whole upload sequence.

Here's the extension function code:

private val executor = Executor { command -> command?.run() }

class WorkResult(private val future: ListenableFuture<*>) {

    fun addListener(listener: () -> Unit) {
        future.addListener(Runnable {
            debugLog("work result listener runnable called")
            listener()
        }, executor)
    }

}

internal fun ListenableFuture<*>.toWorkResult(): WorkResult {
    return WorkResult(this)
}

When I add listeners to WorkResult, they are all called immediately, without waiting for the actual work to complete. Any thought on this?

Blackheart answered 13/11, 2018 at 12:36 Comment(2)
Did you solve this problem?Alissaalistair
only the first part of itAmboceptor
A
2

Until a proper solution is found for this (w/o GCed errors etc), a rudimentary approach could be to create another WorkRequest and chain it as the last work request to handle the state.

Ofcourse, you would have to handle the error states separately (And always return Result.success for each WorkRequest) to allow propagation through the chain.

This is by no means a sustainable approach, but rather a quick fix if necessary

Aldos answered 6/5, 2019 at 14:49 Comment(0)
A
0

The problem is not observed if you get the result with liveData like this, instead of using ListenableFuture

WorkManager.getInstance()
.getWorkInfoByIdLiveData(cloudSyncOneTimeWork.id)
.observe(yourLifecycle, yourObserver)

If you don't want to tie it to a lifecycleowner you can call it like this :

WorkManager.getInstance()
.getWorkInfoByIdLiveData(cloudSyncOneTimeWork.id)
.observeForever(yourObserver)

If you do so you are responsible to unregister the listener when you want

Apsis answered 8/2, 2019 at 16:53 Comment(3)
The problem with livedata is that you need a lifecycleowner for it to work. you don't have that in your repository, where i have work schedulingAmboceptor
that's not true, you can use livedata.observeForever(observer) without specifying lifecycleowner (developer.android.com/reference/android/arch/lifecycle/…)Apsis
i've tried it. it get GCed on some devices (hi samsung) before i get the success statusAmboceptor

© 2022 - 2024 — McMap. All rights reserved.