Począwszy od Usług Google Play w wersji 9.0.0, możesz używać interfejsu API Task
oraz
jest liczba metod, które zwracają dyrektywę Task
lub jej podklasy. Task
to interfejs API, który
reprezentuje wywołania metod asynchronicznych, podobne do funkcji PendingResult
w poprzednim
wersji Usług Google Play.
Wyniki zadań związane z obsługą
Typową metodą zwracającą Task
jest FirebaseAuth.signInAnonymously()
.
Zwraca wartość Task<AuthResult>
, co oznacza, że zadanie zostanie zwrócone.
obiekt AuthResult
w chwili powodzenia:
Task<AuthResult> task = FirebaseAuth.getInstance().signInAnonymously();
Aby otrzymać powiadomienie o pomyślnym wykonaniu zadania, dołącz OnSuccessListener
:
task.addOnSuccessListener(new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { // Task completed successfully // ... } });
Aby otrzymać powiadomienie o nieudanym zadaniu, dołącz OnFailureListener
:
task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
Aby zapewnić obsługę sukcesów i błędów w tym samym detektorze, dołącz załącznik
OnCompleteListener
:
task.addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { // Task completed successfully AuthResult result = task.getResult(); } else { // Task failed with an exception Exception exception = task.getException(); } } });
Regulacja brwi nitką
Detektory dołączone do wątku są uruchamiane w głównym wątku aplikacji (UI)
domyślnie. Przy dołączaniu detektora możesz też określić Executor
, która jest
używane do planowania detektorów.
// Create a new ThreadPoolExecutor with 2 threads for each processor on the // device and a 60 second keep-alive time. int numCores = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor executor = new ThreadPoolExecutor(numCores * 2, numCores *2, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); task.addOnCompleteListener(executor, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // ... } });
Detektory ograniczone do aktywności
Jeśli nasłuchujesz wyników zadań w interfejsie Activity
, możesz dodać
detektory do zadania ograniczone do aktywności. Tacy detektory są usunięci podczas
metody onStop
w Twojej aktywności, by słuchacze nie byli wywoływani
gdy aktywność nie jest już widoczna.
Activity activity = MainActivity.this; task.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // ... } });
Łańcuch
Jeśli używasz wielu interfejsów API, które zwracają kod Task
, możesz je połączyć w łańcuch
i kontynuacji. Pozwala to uniknąć głęboko zagnieżdżonych wywołań zwrotnych i konsolidacji
obsługi błędów w łańcuchach zadań.
Na przykład metoda doSomething
zwraca Task<String>
, ale wymaga
typ AuthResult
, który zostanie pobrany asynchronicznie z zadania:
public Task<String> doSomething(AuthResult authResult) { // ... }
Za pomocą metody Task.continueWithTask
można połączyć w łańcuch te 2 zadania:
Task<AuthResult> signInTask = FirebaseAuth.getInstance().signInAnonymously(); signInTask.continueWithTask(new Continuation<AuthResult, Task<String>>() { @Override public Task<String> then(@NonNull Task<AuthResult> task) throws Exception { // Take the result from the first task and start the second one AuthResult result = task.getResult(); return doSomething(result); } }).addOnSuccessListener(new OnSuccessListener<String>() { @Override public void onSuccess(String s) { // Chain of tasks completed successfully, got result from last task. // ... } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // One of the tasks in the chain failed with an exception. // ... } });
Blokowanie
Jeśli program jest już wykonywany w wątku w tle, możesz zablokować zadanie synchroniczne, aby uzyskać wyniki i uniknąć wywołań zwrotnych:
try { // Block on a task and get the result synchronously. This is generally done // when executing a task inside a separately managed background thread. Doing this // on the main (UI) thread can cause your application to become unresponsive. AuthResult authResult = Tasks.await(task); } catch (ExecutionException e) { // The Task failed, this is the same exception you'd get in a non-blocking // failure handler. // ... } catch (InterruptedException e) { // An interrupt occurred while waiting for the task to complete. // ... }
Możesz też określić limit czasu podczas blokowania zadania, aby aplikacja nie zawiesza się:
try { // Block on the task for a maximum of 500 milliseconds, otherwise time out. AuthResult authResult = Tasks.await(task, 500, TimeUnit.MILLISECONDS); } catch (ExecutionException e) { // ... } catch (InterruptedException e) { // ... } catch (TimeoutException e) { // Task timed out before it could complete. // ... }
Interoperacyjność
Task
pasuje koncepcyjnie do kilku popularnych metod zarządzania w Androidzie
asynchroniczny i Task
można łatwo przekonwertować na inny
elementów podstawowych, w tym współprogramów ListenableFuture
i Kotlin, które są
polecane przez AndroidaX.
Oto przykład użycia właściwości Task
:
// ... simpleTask.addOnCompleteListener(this) { completedTask -> textView.text = completedTask.result }
Kotlin Coroutine
Wykorzystanie
Dodaj do projektu następującą zależność i użyj poniższego kodu do konwersji
z: Task
.
Gradle (build.gradle
na poziomie modułu, zwykle app/build.gradle
)
// Source: https://github.com/Kotlin/kotlinx.coroutines/tree/master/integration/kotlinx-coroutines-play-services implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3'
Krótki opis
import kotlinx.coroutines.tasks.await // ... textView.text = simpleTask.await() }
Gujawa – ListenableFuture
Dodaj do projektu następującą zależność i użyj poniższego kodu do konwersji
z: Task
.
Gradle (build.gradle
na poziomie modułu, zwykle app/build.gradle
)
implementation "androidx.concurrent:concurrent-futures:1.2.0"
Krótki opis
import com.google.common.util.concurrent.ListenableFuture // ... /** Convert Task to ListenableFuture. */ fun <T> taskToListenableFuture(task: Task<T>): ListenableFuture<T> { return CallbackToFutureAdapter.getFuture { completer -> task.addOnCompleteListener { completedTask -> if (completedTask.isCanceled) { completer.setCancelled() } else if (completedTask.isSuccessful) { completer.set(completedTask.result) } else { val e = completedTask.exception if (e != null) { completer.setException(e) } else { throw IllegalStateException() } } } } } // ... this.listenableFuture = taskToListenableFuture(simpleTask) this.listenableFuture?.addListener( Runnable { textView.text = listenableFuture?.get() }, ContextCompat.getMainExecutor(this) )
Dostrzeżony RxJava2
Oprócz względnej biblioteki asynchronicznej dodaj następującą zależność
do swojego projektu i użyj poniższego kodu do konwersji z Task
.
Gradle (build.gradle
na poziomie modułu, zwykle app/build.gradle
)
// Source: https://github.com/ashdavies/rx-tasks implementation 'io.ashdavies.rx.rxtasks:rx-tasks:2.2.0'
Krótki opis
import io.ashdavies.rx.rxtasks.toSingle import java.util.concurrent.TimeUnit // ... simpleTask.toSingle(this).subscribe { result -> textView.text = result }