بدءًا من الإصدار 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.7.3'
المقتطف
import kotlinx.coroutines.tasks.await // ... textView.text = simpleTask.await() }
مستقبل استماع جوفا
أضِف الاعتمادية التالية إلى مشروعك واستخدِم الرمز أدناه للتحويل من 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 }