פרוטוקול Threading ב-CoroutineWorker

למשתמשי Kotlin, ‏WorkManager מספק תמיכה ברמה הגבוהה ביותר בפונקציות רפליקות (coroutines). כדי להתחיל, צריך לכלול את work-runtime-ktx בקובץ ה-gradle. במקום להרחיב את Worker, צריך להרחיב את CoroutineWorker, שיש לה גרסה מושהית של doWork(). לדוגמה, אם רוצים ליצור CoroutineWorker פשוט כדי לבצע פעולות רשת מסוימות, צריך לבצע את הפעולות הבאות:

class CoroutineDownloadWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        val data = downloadSynchronously("https://www.google.com")
        saveData(data)
        return Result.success()
    }
}

שימו לב ש-CoroutineWorker.doWork() היא פונקציה מושהה. בניגוד ל-Worker, הקוד הזה לא פועל ב-Executor שצוין ב-Configuration. במקום זאת, הערך שמוגדר כברירת מחדל הוא Dispatchers.Default. אפשר להתאים אישית את האפשרות הזו על ידי הזנת CoroutineContext משלכם. בדוגמה שלמעלה, מומלץ לבצע את הפעולות האלה ב-Dispatchers.IO באופן הבא:

class CoroutineDownloadWorker(
    context: Context,
    params: WorkerParameters
) : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result {
        withContext(Dispatchers.IO) {
            val data = downloadSynchronously("https://www.google.com")
            saveData(data)
            return Result.success()
        }
    }
}

CoroutineWorker מטפל בהפסקות באופן אוטומטי על ידי ביטול של פונקציית ה-coroutine והעברת אותות הביטול. אין צורך לעשות שום דבר מיוחד כדי לטפל בהשבתות עבודה.

הפעלת CoroutineWorker בתהליך אחר

אפשר גם לקשר עובד לתהליך ספציפי באמצעות RemoteCoroutineWorker, הטמעה של ListenableWorker.

הפונקציה RemoteCoroutineWorker מקשרת לתהליך ספציפי באמצעות שני ארגומנטים נוספים שצריך לספק כחלק מנתוני הקלט בזמן היצירה של בקשת העבודה: ARGUMENT_CLASS_NAME ו-ARGUMENT_PACKAGE_NAME.

הדוגמה הבאה ממחישה יצירה של בקשת עבודה שמקושרת לתהליך ספציפי:

Kotlin

val PACKAGE_NAME = "com.example.background.multiprocess"

val serviceName = RemoteWorkerService::class.java.name
val componentName = ComponentName(PACKAGE_NAME, serviceName)

val data: Data = Data.Builder()
   .putString(ARGUMENT_PACKAGE_NAME, componentName.packageName)
   .putString(ARGUMENT_CLASS_NAME, componentName.className)
   .build()

return OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker::class.java)
   .setInputData(data)
   .build()

Java

String PACKAGE_NAME = "com.example.background.multiprocess";

String serviceName = RemoteWorkerService.class.getName();
ComponentName componentName = new ComponentName(PACKAGE_NAME, serviceName);

Data data = new Data.Builder()
        .putString(ARGUMENT_PACKAGE_NAME, componentName.getPackageName())
        .putString(ARGUMENT_CLASS_NAME, componentName.getClassName())
        .build();

return new OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker.class)
        .setInputData(data)
        .build();

לכל RemoteWorkerService, צריך גם להוסיף הגדרת שירות בקובץ AndroidManifest.xml:

<manifest ... >
    <service
            android:name="androidx.work.multiprocess.RemoteWorkerService"
            android:exported="false"
            android:process=":worker1" />

        <service
            android:name=".RemoteWorkerService2"
            android:exported="false"
            android:process=":worker2" />
    ...
</manifest>