Search code examples
androidandroid-workmanager

WorkManager: ResolvableFuture can only be called from within the same library group prefix


For some time in my ListenableWorker class I have used the following:

public ListenableFuture<Result> startWork() {
    ResolvableFuture<Result> resolvableFuture = ResolvableFuture.create();
    startSomeAsyncStuff(resolvableFuture);
    return resolvableFuture;
}

Basically, I start some asynchronous work, passing resolvableFuture into that function. When the async work is done, I call the following on that resolvableFuture object passed from my ListenableWorker:

resolvableFuture.set(Result.success());

This has worked well, and still appears to, but I'm now seeing the following lint error message against ResolvableFuture.create():

ResolvableFuture can only be called from within the same library group prefix

It still compiles, but this warning bothers me. What is the correct way to do this now?


Solution

  • You shouldn't be using ResolvableFuture at all, much less the internal version used by WorkManager.

    Instead, you should be using the AndroidX Concurrent library:

    androidx.concurrent:concurrent-futures:1.0.0 provides CallbackToFutureAdapter class, a minimalistic utility that allows to wrap callback based code and return instances of ListenableFuture

    You'll note in the 1.0.0-beta01 release notes that even the AndroidX Concurrent Library has removed ResolveableFuture from its public API.

    The Javadoc for CallbackToFutureAdapter has a full example of what this looks like:

    public ListenableFuture<Result> startWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {
             // Your method can call set() or setException() on the
             // Completer to signal completion
             startSomeAsyncStuff(completer);
    
             // This value is used only for debug purposes: it will be used 
             // in toString() of returned future or error cases.
             return "startSomeAsyncStuff";
        });
    }
    

    So you'd use CallbackToFutureAdapter.Completer in place of a ResolvableFuture in your startSomeAsyncStuff method.