Cómo ejecutar subprocesos en ListenableWorker
Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
En ciertas situaciones, es posible que debas proporcionar una estrategia de subprocesos personalizada. Para
Por ejemplo, quizás debas administrar una operación asíncrona basada en devoluciones de llamada.
WorkManager admite este caso de uso con
ListenableWorker
ListenableWorker
es la API de trabajador más básica.
Worker
,
CoroutineWorker
y
RxWorker
derivan de esta clase. R
ListenableWorker
solo indica cuándo debe comenzar, detenerse y salir el trabajo.
la conversación depende completamente de ti. El indicador de inicio de trabajo se invoca en la puerta de enlace
por lo que es muy importante que vayas a un subproceso en segundo plano de tu
elegir manualmente.
El método abstracto
ListenableWorker.startWork()
muestra un ListenableFuture
del
Result
R
ListenableFuture
es una interfaz liviana: es un Future
que proporciona
para adjuntar objetos de escucha y propagar excepciones. En la
startWork
, se espera que muestres un ListenableFuture
, que
se establecerá con el Result
de la operación una vez que se complete. Puedes crear
ListenableFuture
instancias de una de estas dos maneras:
- Si usas Guava, utiliza
ListeningExecutorService
.
- De lo contrario, incluye
councurrent-futures
en tu archivo de Gradle y usar
CallbackToFutureAdapter
Si quisieras ejecutar un trabajo basado en una devolución de llamada asíncrona, tendrías que
haz algo como esto:
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;
});
}
}
¿Qué sucede si tu trabajo está
detenido?
Un elemento ListenableFuture
de ListenableWorker
siempre se cancela cuando el trabajo se
se espera que se detengan. Con un CallbackToFutureAdapter
, solo debes agregar un
objeto de escucha de cancelación, de la siguiente manera:
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;
});
}
}
Cómo ejecutar un ListenableWorker en un proceso diferente
También puedes vincular un trabajador a un proceso específico mediante RemoteListenableWorker
, que es una implementación de ListenableWorker
.
RemoteListenableWorker
vincula un proceso específico con dos argumentos adicionales que puedes proporcionar como parte de los datos de entrada cuando compilas la solicitud de trabajo: ARGUMENT_CLASS_NAME
y ARGUMENT_PACKAGE_NAME
.
En el siguiente ejemplo, se muestra cómo compilar una solicitud de trabajo vinculada a un proceso específico:
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();
Para cada RemoteWorkerService
, también debes agregar una definición del servicio en el archivo 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>
Ejemplos
El contenido y las muestras de código que aparecen en esta página están sujetas a las licencias que se describen en la Licencia de Contenido. Java y OpenJDK son marcas registradas de Oracle o sus afiliados.
Última actualización: 2025-07-27 (UTC)
[[["Fácil de comprender","easyToUnderstand","thumb-up"],["Resolvió mi problema","solvedMyProblem","thumb-up"],["Otro","otherUp","thumb-up"]],[["Falta la información que necesito","missingTheInformationINeed","thumb-down"],["Muy complicado o demasiados pasos","tooComplicatedTooManySteps","thumb-down"],["Desactualizado","outOfDate","thumb-down"],["Problema de traducción","translationIssue","thumb-down"],["Problema con las muestras o los códigos","samplesCodeIssue","thumb-down"],["Otro","otherDown","thumb-down"]],["Última actualización: 2025-07-27 (UTC)"],[],[],null,["# Threading in ListenableWorker\n\nIn certain situations, you may need to provide a custom threading strategy. For\nexample, you may need to handle a callback-based asynchronous operation.\nWorkManager supports this use case with\n[`ListenableWorker`](/reference/androidx/work/ListenableWorker).\n`ListenableWorker` is the most basic worker API;\n[`Worker`](/reference/androidx/work/Worker),\n[`CoroutineWorker`](/reference/kotlin/androidx/work/CoroutineWorker), and\n[`RxWorker`](/reference/androidx/work/RxWorker) all derive from this class. A\n`ListenableWorker` only signals when the work should start and stop and leaves\nthe threading entirely up to you. The start work signal is invoked on the main\nthread, so it is very important that you go to a background thread of your\nchoice manually.\n\nThe abstract method\n[`ListenableWorker.startWork()`](/reference/androidx/work/ListenableWorker#startWork())\nreturns a `ListenableFuture` of the\n[`Result`](/reference/androidx/work/ListenableWorker.Result). A\n`ListenableFuture` is a lightweight interface: it is a `Future` that provides\nfunctionality for attaching listeners and propagating exceptions. In the\n`startWork` method, you are expected to return a `ListenableFuture`, which you\nwill set with the `Result` of the operation once it's completed. You can create\n`ListenableFuture` instances in one of two ways:\n\n1. If you use Guava, use `ListeningExecutorService`.\n2. Otherwise, include [`councurrent-futures`](/jetpack/androidx/releases/concurrent#declaring_dependencies) in your gradle file and use [`CallbackToFutureAdapter`](/reference/androidx/concurrent/futures/CallbackToFutureAdapter).\n\nIf you wanted to execute some work based on an asynchronous callback, you would\ndo something like this: \n\n### Kotlin\n\n```kotlin\nclass CallbackWorker(\n context: Context,\n params: WorkerParameters\n) : ListenableWorker(context, params) {\n override fun startWork(): ListenableFuture\u003cResult\u003e {\n return CallbackToFutureAdapter.getFuture { completer -\u003e\n val callback = object : Callback {\n var successes = 0\n\n override fun onFailure(call: Call, e: IOException) {\n completer.setException(e)\n }\n\n override fun onResponse(call: Call, response: Response) {\n successes++\n if (successes == 100) {\n completer.set(Result.success())\n }\n }\n }\n\n repeat(100) {\n downloadAsynchronously(\"https://example.com\", callback)\n }\n\n callback\n }\n }\n}\n```\n\n### Java\n\n```java\npublic class CallbackWorker extends ListenableWorker {\n\n public CallbackWorker(Context context, WorkerParameters params) {\n super(context, params);\n }\n\n @NonNull\n @Override\n public ListenableFuture\u003cResult\u003e startWork() {\n return CallbackToFutureAdapter.getFuture(completer -\u003e {\n Callback callback = new Callback() {\n int successes = 0;\n\n @Override\n public void onFailure(Call call, IOException e) {\n completer.setException(e);\n }\n\n @Override\n public void onResponse(Call call, Response response) {\n successes++;\n if (successes == 100) {\n completer.set(Result.success());\n }\n }\n };\n\n for (int i = 0; i \u003c 100; i++) {\n downloadAsynchronously(\"https://www.example.com\", callback);\n }\n return callback;\n });\n }\n}\n```\n\nWhat happens if your work is\n[stopped](/topic/libraries/architecture/workmanager/how-to/managing-work#cancelling)?\nA `ListenableWorker`'s `ListenableFuture` is always cancelled when the work is\nexpected to stop. Using a `CallbackToFutureAdapter`, you simply have to add a\ncancellation listener, as follows: \n\n### Kotlin\n\n```kotlin\nclass CallbackWorker(\n context: Context,\n params: WorkerParameters\n) : ListenableWorker(context, params) {\n override fun startWork(): ListenableFuture\u003cResult\u003e {\n return CallbackToFutureAdapter.getFuture { completer -\u003e\n val callback = object : Callback {\n var successes = 0\n\n override fun onFailure(call: Call, e: IOException) {\n completer.setException(e)\n }\n\n override fun onResponse(call: Call, response: Response) {\n ++successes\n if (successes == 100) {\n completer.set(Result.success())\n }\n }\n }\n\n completer.addCancellationListener(cancelDownloadsRunnable, executor)\n\n repeat(100) {\n downloadAsynchronously(\"https://example.com\", callback)\n }\n\n callback\n }\n }\n}\n```\n\n### Java\n\n```java\npublic class CallbackWorker extends ListenableWorker {\n\n public CallbackWorker(Context context, WorkerParameters params) {\n super(context, params);\n }\n\n @NonNull\n @Override\n public ListenableFuture\u003cResult\u003e startWork() {\n return CallbackToFutureAdapter.getFuture(completer -\u003e {\n Callback callback = new Callback() {\n int successes = 0;\n\n @Override\n public void onFailure(Call call, IOException e) {\n completer.setException(e);\n }\n\n @Override\n public void onResponse(Call call, Response response) {\n ++successes;\n if (successes == 100) {\n completer.set(Result.success());\n }\n }\n };\n\n completer.addCancellationListener(cancelDownloadsRunnable, executor);\n\n for (int i = 0; i \u003c 100; ++i) {\n downloadAsynchronously(\"https://www.example.com\", callback);\n }\n return callback;\n });\n }\n}\n```\n\nRunning a ListenableWorker in a different process\n-------------------------------------------------\n\nYou can also bind a worker to a specific process by using\n[`RemoteListenableWorker`](/reference/kotlin/androidx/work/multiprocess/RemoteListenableWorker),\nan implementation of `ListenableWorker`.\n\n`RemoteListenableWorker` binds to a specific process with two extra arguments\nthat you provide as part of the input data when building the work request:\n`ARGUMENT_CLASS_NAME` and `ARGUMENT_PACKAGE_NAME`.\n\nThe following example demonstrates building a work request that is bound to a\nspecific process: \n\n### Kotlin\n\n```kotlin\nval PACKAGE_NAME = \"com.example.background.multiprocess\"\n\nval serviceName = RemoteWorkerService::class.java.name\nval componentName = ComponentName(PACKAGE_NAME, serviceName)\n\nval data: Data = Data.Builder()\n .putString(ARGUMENT_PACKAGE_NAME, componentName.packageName)\n .putString(ARGUMENT_CLASS_NAME, componentName.className)\n .build()\n\nreturn OneTimeWorkRequest.Builder(ExampleRemoteListenableWorker::class.java)\n .setInputData(data)\n .build()\n```\n\n### Java\n\n```java\nString PACKAGE_NAME = \"com.example.background.multiprocess\";\n\nString serviceName = RemoteWorkerService.class.getName();\nComponentName componentName = new ComponentName(PACKAGE_NAME, serviceName);\n\nData data = new Data.Builder()\n .putString(ARGUMENT_PACKAGE_NAME, componentName.getPackageName())\n .putString(ARGUMENT_CLASS_NAME, componentName.getClassName())\n .build();\n\nreturn new OneTimeWorkRequest.Builder(ExampleRemoteListenableWorker.class)\n .setInputData(data)\n .build();\n```\n\nFor each `RemoteWorkerService`, you also need to add a service definition in\nyour `AndroidManifest.xml` file: \n\n```xml\n\u003cmanifest ... \u003e\n \u003cservice\n android:name=\"androidx.work.multiprocess.RemoteWorkerService\"\n android:exported=\"false\"\n android:process=\":worker1\" /\u003e\n\n \u003cservice\n android:name=\".RemoteWorkerService2\"\n android:exported=\"false\"\n android:process=\":worker2\" /\u003e\n ...\n\u003c/manifest\u003e\n```\n\nSamples\n-------\n\n- [WorkManagerMultiProcessSample](https://github.com/android/architecture-components-samples/tree/main/WorkManagerMultiprocessSample)"]]