ListenableWorker 中的執行緒
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
在某些情況下,您可能需要提供自訂執行緒策略。適用對象
例如,您可能需要處理以回呼為基礎的非同步作業。
WorkManager 支援以下用途:
ListenableWorker
。
ListenableWorker
是最基本的工作站 API;
Worker
,
CoroutineWorker
和
RxWorker
都來自這個類別。A 罩杯
只有在工作開始和停止及離開時,ListenableWorker
才會發出信號
要完全由您決定系統會在主要主機上叫用啟動工作信號
所以一定要前往
抽象方法
ListenableWorker.startWork()
敬上
會傳回ListenableFuture
Result
。A 罩杯
ListenableFuture
是輕量的介面,也就是提供以下服務的 Future
附加事件監聽器及傳播例外狀況的功能在
startWork
方法,應傳回 ListenableFuture
,
會在作業完成後,根據作業的 Result
進行設定。您可以建立
ListenableFuture
執行個體,以下列兩種方式之一:
- 如果您使用的是 Guava,請使用
ListeningExecutorService
。
- 否則,請加入
councurrent-futures
敬上
,然後使用
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;
});
}
}
如果您的工作是
停止?
在工作期間,ListenableWorker
的 ListenableFuture
一律會取消
預期會停止使用 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())
}
}
}
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;
});
}
}
以其他程序執行 ReadableWorker
您也可以使用 ListenableWorker
導入 RemoteListenableWorker
,將工作站繫結至特定程序。
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>
範例
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[[["容易理解","easyToUnderstand","thumb-up"],["確實解決了我的問題","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["缺少我需要的資訊","missingTheInformationINeed","thumb-down"],["過於複雜/步驟過多","tooComplicatedTooManySteps","thumb-down"],["過時","outOfDate","thumb-down"],["翻譯問題","translationIssue","thumb-down"],["示例/程式碼問題","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],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)"]]