diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-05-01 22:27:19 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-01 22:27:19 +0000 |
commit | d79cc007b8689c6511756d923721f292658b0c20 (patch) | |
tree | 6148ce3c151f86350a3682b09deb8fbc90f13f90 | |
parent | 76c5f49d8fed80389488f0b1f9b9d23f59562e05 (diff) | |
parent | 9896fb1bf5a6dc1dc9a5390672b169c4145ef84f (diff) | |
download | docs-master.tar.gz |
Merge "Android API guidelines: describe intended use cases for OutcomeReceiver" into mainHEADmastermain
-rw-r--r-- | api-guidelines/methods.md | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/api-guidelines/methods.md b/api-guidelines/methods.md index ca4575a..14ad03a 100644 --- a/api-guidelines/methods.md +++ b/api-guidelines/methods.md @@ -1485,6 +1485,55 @@ cautions against using `default` methods in cases where multiple inheritance is likely; however, this is rare for callbacks and in practice we have only seen method naming collisions on commonly-extended classes like `Activity`. +### Use `android.os.OutcomeReceiver` when modeling a non-blocking function call + +[`OutcomeReceiver<R,E>`](https://developer.android.com/reference/android/os/OutcomeReceiver) +reports a result value `R` when successful or `E : Throwable` otherwise - the +same things a plain method call can do. Use `OutcomeReceiver` as the callback +type when converting a blocking method that returns a result or throws an +exception to a non-blocking async method: + +```java +interface FooType { + // Before: + public FooResult requestFoo(FooRequest request); + + // After: + public void requestFooAsync(FooRequest request, Executor executor, + OutcomeReceiver<FooResult, Throwable> callback); +} +``` + +Async methods converted in this way always return `void`. Any result that +`requestFoo` would return is instead reported to `requestFooAsync`'s `callback` +parameter's `OutcomeReceiver.onResult` by calling it on the provided `executor`. +Any exception that `requestFoo` would throw is instead reported to the +`OutcomeReceiver.onError` method in the same way. + +Using `OutcomeReceiver` for reporting async method results also affords a simple +Kotlin `suspend fun` wrapper for async methods using the +`Continuation.asOutcomeReceiver` extension from `androidx.core:core-ktx`: + +```kotlin +suspend fun FooType.requestFoo(request: FooRequest): FooResult = + suspendCancellableCoroutine { continuation -> + requestFooAsync(request, Runnable::run, continuation.asOutcomeReceiver()) + } +``` + +Extensions like the above enable Kotlin clients to call non-blocking async +methods with the convenience of a plain function call without blocking the +calling thread. These 1-1 extensions for platform APIs may be offered as part of +the `androidx.core:core-ktx` artifact in Jetpack when combined with standard +version compatibility checks and considerations. See the documentation for +[asOutcomeReceiver](https://developer.android.com/reference/kotlin/androidx/core/os/package-summary#(kotlin.coroutines.Continuation).asOutcomeReceiver()) +for more information, cancellation considerations and samples. + +Async methods that do not match the semantics of a method returning a result +or throwing an exception when its work is complete should **not** use +`OutcomeReceiver` as a callback type. Instead consider one of the other options +listed below. + ### Prefer functional interfaces over creating new single abstract method (SAM) types <a name="callbacks-sam"></a> API level 24 added the `java.util.function.*` @@ -1501,8 +1550,6 @@ Consider using these generic interfaces, rather than creating new ones: * `Consumer<T>`: `(T) -> Unit` * `Function<T,R>`: `(T) -> R` * `Predicate<T>`: `(T) -> Boolean` -* [`OutcomeReceiver<R,E>`](https://developer.android.com/reference/android/os/OutcomeReceiver) - (unary result `R` when successful or `E : Throwable` otherwise) * [many more available in reference docs](https://developer.android.com/reference/java/util/function/package-summary.html) #### Placement of SAM parameters |