بدءًا من الإصدار 9.0.0 من خدمات Google Play، يمكنك استخدام واجهة برمجة التطبيقات Task
وعدد من الطرق التي تعرض Task
أو فئاتها الفرعية. Task
هي واجهة برمجة تطبيقات
تمثل طلبات الطرق غير المتزامنة، وتشبه واجهة برمجة التطبيقات 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 = 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
مباشرةً إلى إعدادات أولية
أخرى، بما في ذلك كورتيون 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.4.1'
المقتطف
import kotlinx.coroutines.tasks.await // ... textView.text = simpleTask.await() }
مهرجان "جوافا" القابل للاستماع
أضِف الاعتمادية التالية إلى مشروعك واستخدِم الرمز أدناه لتحويلها من Task
.
Gradle (عادةً على مستوى الوحدة build.gradle
، app/build.gradle
)
implementation "androidx.concurrent:concurrent-futures:1.1.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 }