بدءًا من الإصدار 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(); } } });
خيط
يتم تلقائيًا تشغيل أدوات معالجة البيانات المرتبطة بسلسلة محادثات على سلسلة التعليمات الرئيسية للتطبيق (واجهة المستخدم). عند إرفاق مستمع، يمكنك أيضًا تحديد 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() }
قناة Guava ListenableFuture
أضِف التبعية التالية إلى مشروعك واستخدِم الرمز أدناه لتحويله من 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 }