با شروع خدمات Google Play نسخه 9.0.0، میتوانید از Task
API و تعدادی از روشهایی که Task
یا زیر کلاسهای آن را برمیگردانند استفاده کنید. Task
یک API است که شبیه به PendingResult
در نسخههای قبلی سرویسهای Google Play تماسهای متد ناهمزمان را نشان میدهد.
رسیدگی به نتایج کار
یک روش رایج که یک Task
را برمی گرداند FirebaseAuth.signInAnonymously()
است. یک Task<AuthResult>
برمیگرداند که به این معنی است که وقتی کار موفق شد، یک شی AuthResult
را برمیگرداند:
Task<AuthResult> task = FirebaseAuth.getInstance().signInAnonymously();
برای اطلاع از موفقیت آمیز بودن کار، یک OnSuccessListener
را ضمیمه کنید:
task.addOnSuccessListener(new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { // Task completed successfully // ... } });
برای اطلاع از عدم موفقیت کار، یک OnFailureListener
را ضمیمه کنید:
task.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
برای مدیریت موفقیت و شکست در یک شنونده، یک 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(); } } });
نخ زنی
شنوندگان متصل به یک رشته به طور پیش فرض بر روی رشته اصلی برنامه (UI) اجرا می شوند. هنگام پیوست کردن شنونده، می توانید یک Executor
را نیز مشخص کنید که برای زمان بندی شنوندگان استفاده می شود.
// 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) { // ... } });
شنوندگان با محدوده فعالیت
اگر در حال گوش دادن به نتایج کار در یک Activity
هستید، ممکن است بخواهید شنوندگان با محدوده فعالیت را به کار اضافه کنید. این شنوندهها در روش onStop
از Activity شما حذف میشوند تا وقتی که Activity دیگر قابل مشاهده نیست، شنوندگان شما فراخوانی نشوند.
Activity activity = MainActivity.this; task.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // ... } });
زنجیر زدن
اگر از چندین API استفاده میکنید که Task
برمیگرداند، میتوانید با استفاده از یک ادامه، آنها را به هم متصل کنید. این به جلوگیری از تماسهای عمیق تو در تو کمک میکند و مدیریت خطا را برای زنجیره وظایف یکپارچه میکند.
به عنوان مثال، متد doSomething
یک Task<String>
برمیگرداند اما به یک AuthResult
نیاز دارد که به صورت ناهمزمان از یک کار دریافت میکنیم:
public Task<String> doSomething(AuthResult authResult) { // ... }
با استفاده از متد Task.continueWithTask
، میتوانیم این دو وظیفه را زنجیرهای کنیم:
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. // ... } });
مسدود کردن
اگر برنامه شما قبلاً در یک رشته پسزمینه اجرا میشود، میتوانید یک کار را مسدود کنید تا نتیجه را به صورت همزمان دریافت کنید و از تماسهای برگشتی اجتناب کنید:
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. // ... }
همچنین میتوانید هنگام مسدود کردن یک کار، یک بازه زمانی تعیین کنید تا برنامه شما هنگ نشود:
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. // ... }
قابلیت همکاری
یک Task
از نظر مفهومی با چندین رویکرد محبوب Android برای مدیریت کدهای ناهمزمان مطابقت دارد، و یک Task
را می توان به سادگی به سایر موارد اولیه، از جمله ListenableFuture
و Kotlin که توسط AndroidX توصیه می شود، تبدیل کرد.
در اینجا یک مثال با استفاده از Task
آورده شده است:
// ... simpleTask.addOnCompleteListener(this) { completedTask -> textView.text = completedTask.result }
کاتلین کوروتین
استفاده
وابستگی زیر را به پروژه خود اضافه کنید و از کد زیر برای تبدیل از یک Task
استفاده کنید.
Gradle (سطح ماژول build.gradle
، معمولا 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'
قطعه
import kotlinx.coroutines.tasks.await // ... textView.text = simpleTask.await() }
Guava ListenableFuture
وابستگی زیر را به پروژه خود اضافه کنید و از کد زیر برای تبدیل از یک Task
استفاده کنید.
Gradle (سطح ماژول build.gradle
، معمولا app/build.gradle
)
implementation "androidx.concurrent:concurrent-futures:1.2.0"
قطعه
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) )
RxJava2 قابل مشاهده
علاوه بر کتابخانه نسبی همگام انتخابی، وابستگی زیر را به پروژه خود اضافه کنید و از کد زیر برای تبدیل از یک Task
استفاده کنید.
Gradle (سطح ماژول build.gradle
، معمولا app/build.gradle
)
// Source: https://github.com/ashdavies/rx-tasks implementation 'io.ashdavies.rx.rxtasks:rx-tasks:2.2.0'
قطعه
import io.ashdavies.rx.rxtasks.toSingle import java.util.concurrent.TimeUnit // ... simpleTask.toSingle(this).subscribe { result -> textView.text = result }