اعتبارًا من الإصدار 9.0.0 من "خدمات Google Play"، يمكنك استخدام واجهة برمجة تطبيقات Task
و
عدد من الطرق التي تعرض Task
أو فئات فرعية منها. Task
هي واجهة برمجة تطبيقات represent asynchronous method calls، تشبه 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(); } } });
سلاسل المحادثات
يتم تشغيل المستمعين المرتبطين بسلسلة محادثات في سلسلة المحادثات الرئيسية (واجهة المستخدم) للتطبيق
تلقائيًا. عند إرفاق مستمع، يمكنك أيضًا تحديد 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 = MainActivity.this; task.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { // ... } });
التسلسل
إذا كنت تستخدم واجهات برمجة تطبيقات متعددة تعرض 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
مباشرةً إلى Task
أساسية أخرى، بما في ذلك ListenableFuture
وعمليات التشغيل المتعدّدة في Kotlin، والتيينصح بها AndroidX.
في ما يلي مثال على استخدام Task
:
// ... simpleTask.addOnCompleteListener(this) { completedTask -> textView.text = completedTask.result }
كوروتين في لغة Kotlin
الاستخدام
أضِف التبعية التالية إلى مشروعك واستخدِم الرمز البرمجي أدناه للتحويل
من 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 Observable
أضِف التبعية التالية، بالإضافة إلى مكتبة المهام غير المتزامنة النسبية التي تريدها، إلى مشروعك واستخدِم الرمز البرمجي أدناه للتحويل من 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 }