Thread in HearableWorker
Mantieni tutto organizzato con le raccolte
Salva e classifica i contenuti in base alle tue preferenze.
In alcune situazioni, potrebbe essere necessario fornire una strategia di thread personalizzata. Per
Ad esempio, potresti dover gestire un'operazione asincrona basata su callback.
WorkManager supporta questo caso d'uso con
ListenableWorker
ListenableWorker
è l'API worker di base;
Worker
,
CoroutineWorker
e
RxWorker
tutte derivano da questa classe. R
ListenableWorker
segnala solo quando il lavoro deve iniziare, terminare e se ne va
il thread a te. L'indicatore di avvio del lavoro viene richiamato nell'istanza principale
quindi è molto importante andare in un thread di background della
manualmente.
Il metodo astratto
ListenableWorker.startWork()
restituisce un ListenableFuture
del
Result
. R
ListenableFuture
è un'interfaccia leggera: è un Future
che fornisce
per collegare i listener e propagare le eccezioni. Nella
startWork
, dovresti restituire un ListenableFuture
, che
verrà impostato con Result
dell'operazione una volta completata. Puoi creare
ListenableFuture
di istanze in uno dei due modi seguenti:
- Se usi Guava, usa
ListeningExecutorService
.
- In caso contrario, includi
councurrent-futures
nel file Gradle e utilizzare
CallbackToFutureAdapter
.
Se volessi eseguire alcune operazioni in base a un callback asincrono, dovresti
procedi in questo modo:
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;
});
}
}
Cosa succede se il tuo lavoro è
interrotto?
Il ListenableFuture
di ListenableWorker
viene sempre annullato quando il lavoro viene
è previsto l'arresto. Se usi un CallbackToFutureAdapter
, devi solo aggiungere
listener di annullamento, come segue:
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;
});
}
}
Esecuzione di ListenableWorker in un processo diverso
Puoi anche associare un worker a un processo specifico utilizzando
RemoteListenableWorker
,
un'implementazione di ListenableWorker
.
RemoteListenableWorker
si associa a un processo specifico con due argomenti aggiuntivi
che fornisci come parte dei dati di input durante la creazione della richiesta di lavoro:
ARGUMENT_CLASS_NAME
e ARGUMENT_PACKAGE_NAME
.
L'esempio seguente mostra la creazione di una richiesta di lavoro associata a un
una procedura specifica:
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();
Per ogni RemoteWorkerService
, devi aggiungere anche una definizione di servizio in
il tuo file 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>
Campioni
I campioni di contenuti e codice in questa pagina sono soggetti alle licenze descritte nella Licenza per i contenuti. Java e OpenJDK sono marchi o marchi registrati di Oracle e/o delle sue società consociate.
Ultimo aggiornamento 2025-07-27 UTC.
[[["Facile da capire","easyToUnderstand","thumb-up"],["Il problema è stato risolto","solvedMyProblem","thumb-up"],["Altra","otherUp","thumb-up"]],[["Mancano le informazioni di cui ho bisogno","missingTheInformationINeed","thumb-down"],["Troppo complicato/troppi passaggi","tooComplicatedTooManySteps","thumb-down"],["Obsoleti","outOfDate","thumb-down"],["Problema di traduzione","translationIssue","thumb-down"],["Problema relativo a esempi/codice","samplesCodeIssue","thumb-down"],["Altra","otherDown","thumb-down"]],["Ultimo aggiornamento 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)"]]