androidandroid-workmanagerfirebase-job-dispatcher

When migrating from FirebaseJobDispatcher to AndroidX Workmanager: How do I return a ListenableFuture in startWork?


So per the documentation Firebase JobDispatcher is deprecated and should be migrated to use the WorkManager. I was following the migration guide which said the functionality implemented in a JobService should be migrated to a ListenableWorker. However I am stumped on how to implement startWork(), the guide only says

override fun startWork(): ListenableFuture<ListenableWorker.Result> {
    // Do your work here.
    TODO("Return a ListenableFuture<Result>")
}

I have done a lot of googling but i have not been able to figure out how to implement/use the ListenableFuture in this context to implement the functionality of the JobService, where I called jobFinished and returned a Boolean value to represent if work was still going on. Any help is appreciated


Solution

  • You need to use ListenableWorker if you need to execute asynchronous code. There's a Threading in ListenableWorker documentation page that covers this:

    If you wanted to execute some work based on an asynchronous callback, you would do something like this:

    public class CallbackWorker extends ListenableWorker {
    
        public CallbackWorker(Context context, WorkerParameters params) {
            super(context, params);
        }
    
        @NonNull
        @Override
        public ListenableFuture<Result> startWork() {
            return CallbackToFutureAdapter.getFuture(completer -> {
                Callback callback = new Callback() {
                    int successes = 0;
    
                    @Override
                    public void onFailure(Call call, IOException e) {
                        completer.setException(e);
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) {
                        ++successes;
                        if (successes == 100) {
                            completer.set(Result.success());
                        }
                    }
                };
    
                for (int i = 0; i < 100; ++i) {
                    downloadAsynchronously("https://www.google.com", callback);
                }
                return callback;
            });
        }
    }
    

    A simpler alternative, if you're using kotlin, is to use a CoroutineWorker class.
    If what you need to execute is synchronous, using a Worker class is probably simpler and enough for your use case. This is documented in Threading in Worker.