W niektórych sytuacjach konieczne może być udostępnienie strategii podziału na wątki niestandardowe. Dla:
może na przykład wymagać obsługi operacji asynchronicznej opartych na wywołaniu zwrotnym.
WorkManager obsługuje ten przypadek użycia za pomocą funkcji
ListenableWorker
ListenableWorker to najbardziej podstawowy interfejs API instancji roboczej.
Worker,
CoroutineWorker oraz
RxWorker – wszystkie z tych zajęć. O
Funkcja ListenableWorker tylko sygnalizuje, kiedy zadanie ma się rozpocząć, zatrzymać i wyjść
i układania wątków. Sygnał rozpoczęcia pracy jest wywoływany na głównym
tak ważne jest przejście do wątku w tle
możesz wybrać ręcznie.
Metoda abstrakcyjna
ListenableWorker.startWork()
zwraca ListenableFuture z
Result O
ListenableFuture to uproszczony interfejs. To Future, który zapewnia
do dołączania detektorów i propagowania wyjątków. W
startWork, powinien zostać zwrócony ListenableFuture, którego
zostanie ustawiony na wartość Result operacji po jej zakończeniu. Możesz utworzyć
ListenableFuture instancji na jeden z dwóch sposobów:
- Jeśli używasz Guawy, użyj
ListeningExecutorService. - W przeciwnym razie dołącz
councurrent-futuresw pliku Gradle i użyjCallbackToFutureAdapter
Jeśli chcesz wykonać pracę w oparciu o asynchroniczne wywołanie zwrotne, wykonaj zrób coś takiego:
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; }); } }
Co się stanie, jeśli Twoja praca
zatrzymano?
Zadanie ListenableFuture dla ListenableWorker jest zawsze anulowane, gdy zadanie jest
przestanie działać. Korzystając z CallbackToFutureAdapter, wystarczy dodać
detektor anulowania w ten sposób:
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; }); } }
Uruchamianie elementu ListenableWorker w innym procesie
Możesz też powiązać instancję roboczą z konkretnym procesem za pomocą polecenia
RemoteListenableWorker
implementacją ListenableWorker.
Funkcja RemoteListenableWorker wiąże się z określonym procesem za pomocą 2 dodatkowych argumentów
którą podajesz jako część danych wejściowych podczas tworzenia zlecenia:
ARGUMENT_CLASS_NAME i ARGUMENT_PACKAGE_NAME.
Poniższy przykład pokazuje tworzenie żądania pracy, które jest powiązane z konkretny proces:
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();
W przypadku każdego elementu (RemoteWorkerService) musisz też dodać definicję usługi w:
Twój plik 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>