במצבים מסוימים, יכול להיות שתצטרכו לספק אסטרטגיית שרשורים בהתאמה אישית. עבור
למשל, ייתכן שתצטרכו לטפל בפעולה אסינכרונית שמבוססת על קריאה חוזרת.
ב-WorkManager תומך בתרחיש לדוגמה הזה עם
ListenableWorker
ListenableWorker
הוא ה-API הבסיסי ביותר של Worker;
Worker
,
CoroutineWorker
, וגם
RxWorker
נגזרות מהכיתה הזו. א'
לפי ListenableWorker
אפשר לסמן רק מתי העבודה צריכה להתחיל ולהפסיק, או לצאת ממנה
אתם קובעים את השרשור. אות ההתחלה של העבודה מופעל
לכן חשוב מאוד שתעברו לשרשור הרקע של
בחירה ידנית.
השיטה המופשטת
ListenableWorker.startWork()
מחזירה ListenableFuture
מתוך
Result
. א'
ListenableFuture
הוא ממשק קל: הוא Future
שמספק
פונקציונליות לצירוף מאזינים ולהפצת חריגים. ב
השיטה startWork
, צפויה להחזיר ListenableFuture
,
יוגדר כ-Result
של הפעולה כאשר היא תסתיים. אפשר ליצור
ListenableFuture
מופעים באחת משתי הדרכים הבאות:
- אם משתמשים ב-Guava, צריך להשתמש ב-
ListeningExecutorService
. - אחרת, צריך לכלול
councurrent-futures
בקובץ Gradle ולהשתמשCallbackToFutureAdapter
אם רצית לבצע עבודה מסוימת על סמך קריאה חוזרת אסינכרונית, עושים משהו כזה:
Kotlin
class CallbackWorker( context: Context, params: WorkerParameters ) : ListenableWorker(context, params) { override fun startWork(): ListenableFuture<Result> { return CallbackToFutureAdapter.getFuture { completer -> val callback = object : Callback { var successes = 0 override fun onFailure(call: Call, e: IOException) { completer.setException(e) } override fun onResponse(call: Call, response: Response) { successes++ if (successes == 100) { completer.set(Result.success()) } } } repeat(100) { downloadAsynchronously("https://example.com", callback) } callback } } }
Java
public class CallbackWorker extends ListenableWorker { public CallbackWorker(Context context, WorkerParameters params) { super(context, params); } @NonNull @Override public ListenableFuture<Result> startWork() { return CallbackToFutureAdapter.getFuture(completer -> { Callback callback = new Callback() { int successes = 0; @Override public void onFailure(Call call, IOException e) { completer.setException(e); } @Override public void onResponse(Call call, Response response) { successes++; if (successes == 100) { completer.set(Result.success()); } } }; for (int i = 0; i < 100; i++) { downloadAsynchronously("https://www.example.com", callback); } return callback; }); } }
מה קורה אם העבודה שלכם
נעצר?
ListenableFuture
של ListenableWorker
תמיד מבוטל כשהעבודה
צפוי להפסיק. באמצעות CallbackToFutureAdapter
, צריך רק להוסיף
מבטל את ה-listener, באופן הבא:
Kotlin
class CallbackWorker( context: Context, params: WorkerParameters ) : ListenableWorker(context, params) { override fun startWork(): ListenableFuture<Result> { return CallbackToFutureAdapter.getFuture { completer -> val callback = object : Callback { var successes = 0 override fun onFailure(call: Call, e: IOException) { completer.setException(e) } override fun onResponse(call: Call, response: Response) { ++successes if (successes == 100) { completer.set(Result.success()) } } } completer.addCancellationListener(cancelDownloadsRunnable, executor) repeat(100) { downloadAsynchronously("https://example.com", callback) } callback } } }
Java
public class CallbackWorker extends ListenableWorker { public CallbackWorker(Context context, WorkerParameters params) { super(context, params); } @NonNull @Override public ListenableFuture<Result> startWork() { return CallbackToFutureAdapter.getFuture(completer -> { Callback callback = new Callback() { int successes = 0; @Override public void onFailure(Call call, IOException e) { completer.setException(e); } @Override public void onResponse(Call call, Response response) { ++successes; if (successes == 100) { completer.set(Result.success()); } } }; completer.addCancellationListener(cancelDownloadsRunnable, executor); for (int i = 0; i < 100; ++i) { downloadAsynchronously("https://www.example.com", callback); } return callback; }); } }
הרצת ListenableWorker בתהליך אחר
אפשר גם לקשר עובד לתהליך ספציפי באמצעות
RemoteListenableWorker
יישום של ListenableWorker
.
RemoteListenableWorker
מקושר לתהליך ספציפי עם שני ארגומנטים נוספים
שאתם מספקים כחלק מנתוני הקלט בתהליך היצירה של בקשת העבודה:
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(ExampleRemoteListenableWorker::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(ExampleRemoteListenableWorker.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>