Kapil Garg
Kapil Garg

Reputation: 477

Can someone provide a good Listenable worker example?

I have been digging into ListenableWorker class to create a service using new workmanager. But nowhere have i found any examples. Any source which describes work manager, gives example of Worker class which has a nice doWork method but it doesn't meet my requirements. So i want your help to write a nice service using ListenableWorker which can handle ListenableFuture

I have tried android developer's documentation and in their documentation, they have written about using guava and using concurrent-futures both of which don't provide any example to write a simple service. I also have watched the workmanager release video in which google engineers explain the new API but their examples are all in Kotlin and i don't get the classes to use.

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.work.ListenableWorker;
import androidx.work.WorkerParameters;

import com.google.common.util.concurrent.ListenableFuture;


public class DistanceWorker extends ListenableWorker {

    public DistanceWorker(Context context, WorkerParameters workerParameters){
        super(context, workerParameters);
    }
    @NonNull
    @Override
    public ListenableFuture<Result> startWork() {
        //what to write here ?
    }
}

I just want to return a future and want to know how to resolve or reject that future when my work is done. Please help me understanding it.

Upvotes: 12

Views: 10488

Answers (4)

arango_86
arango_86

Reputation: 4425

Sample code from Android Documentation.

class CallbackWorker(
        context: Context,
        params: WorkerParameters
) : ListenableWorker(context, params) {
    override fun startWork(): ListenableFuture<Result> {
        return CallbackToFutureAdapter.getFuture { completer ->
            val callback = object : Callback {
                var successes = 0

                override fun onFailure(call: Call, e: IOException) {
                    completer.setException(e)
                }

                override fun onResponse(call: Call, response: Response) {
                    successes++
                    if (successes == 100) {
                        completer.set(Result.success())
                    }
                }
            }

            repeat(100) {
                downloadAsynchronously("https://example.com", callback)
            }

            callback
        }
    }
}

Reference:- https://developer.android.com/topic/libraries/architecture/workmanager/advanced/listenableworker

Upvotes: 0

Dan Alboteanu
Dan Alboteanu

Reputation: 10212

you can do like this

override fun startWork(): ListenableFuture<ListenableWorker.Result> {
    // Do your work here

    return CallbackToFutureAdapter.getFuture {
      it.set(Result.success())
    } 
}

Upvotes: 5

febaisi
febaisi

Reputation: 684

I've also had questions on how to use ListenableWorkers using Kotlin. So I built this small example to retrieve location, which I believe it's the most common case to use it.

https://github.com/febaisi/ListenableWorkerExample

Here is a generic basic usage (not tested) - I believe it's just easier checking my project out where I added the complete tested version of this. I get data out of the worker in the Github project, and it's kind of hard to exemplify it here.

    //Enqueue work
    val anyWorkListenableWorker = OneTimeWorkRequest.Builder(AnyWorkListenableWorker::class.java).build()
    workManagerInstance.enqueueUniqueWork("ANY_WORK", ExistingWorkPolicy.KEEP, anyWorkListenableWorker)
class AnyWorkListenableWorker(appContext: Context, workerParams: WorkerParameters)
    : ListenableWorker(appContext, workerParams) {

    private val future : ResolvableFuture<Result> = ResolvableFuture.create()

    override fun startWork(): ListenableFuture<Result> {
        //MAIN THREAD

        CoroutineScope(Default).launch {
            //Launch scope to do work out of the main thread
            doAnyWork()
        }

        return future
    }

    private fun doAnyWork() {
        //Do long work
        future.set(Result.success())
    }
}

Upvotes: 10

Related Questions