Trong một số trường hợp, có thể bạn sẽ cần đưa ra một chiến lược tạo luồng xử lý tuỳ chỉnh. Cho
Ví dụ: bạn có thể cần xử lý hoạt động không đồng bộ dựa trên lệnh gọi lại.
WorkManager hỗ trợ trường hợp sử dụng này bằng
ListenableWorker
.
ListenableWorker
là API trình thực thi cơ bản nhất;
Worker
,
CoroutineWorker
và
RxWorker
đều xuất phát từ lớp học này. Đáp
ListenableWorker
chỉ báo hiệu khi nào công việc phải bắt đầu, dừng lại và rời đi
việc phân luồng hoàn toàn tuỳ thuộc vào bạn. Tín hiệu bắt đầu công việc được gọi trên
nên bạn cần chuyển đến chuỗi nền của
lựa chọn theo cách thủ công.
Phương thức trừu tượng
ListenableWorker.startWork()
sẽ trả về một ListenableFuture
của
Result
. Đáp
ListenableFuture
là một giao diện gọn nhẹ: đây là một Future
cung cấp
chức năng đính kèm trình nghe và truyền ngoại lệ. Trong
startWork
, bạn dự kiến sẽ trả về ListenableFuture
mà bạn
sẽ đặt bằng Result
của thao tác sau khi thao tác đó hoàn tất. Bạn có thể tạo
ListenableFuture
theo một trong hai cách:
- Nếu bạn dùng Guava, hãy sử dụng
ListeningExecutorService
. - Nếu không, hãy bao gồm
councurrent-futures
trong tệp gradle của bạn và sử dụngCallbackToFutureAdapter
.
Nếu muốn thực thi một số công việc dựa trên lệnh gọi lại không đồng bộ, bạn nên hãy làm như sau:
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 } } }
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; }); } }
Điều gì sẽ xảy ra nếu công việc của bạn
đã dừng?
ListenableFuture
của ListenableWorker
luôn bị huỷ khi công việc là
dự kiến dừng lại. Khi sử dụng CallbackToFutureAdapter
, bạn chỉ cần thêm
trình nghe thao tác huỷ như sau:
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 } } }
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; }); } }
Chạy ListenableWorker trong một quy trình khác
Bạn cũng có thể liên kết một worker với một quy trình cụ thể bằng cách sử dụng RemoteListenableWorker
(một cách triển khai của ListenableWorker
).
RemoteListenableWorker
liên kết với một quy trình cụ thể bằng 2 đối số bổ sung ARGUMENT_CLASS_NAME
và ARGUMENT_PACKAGE_NAME
mà bạn cung cấp dưới dạng một phần của dữ liệu đầu vào khi tạo yêu cầu công việc.
Ví dụ sau đây minh hoạ việc xây dựng một yêu cầu công việc ràng buộc với một quy trình cụ thể:
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()
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();
Đối với mỗi RemoteWorkerService
, bạn cũng cần thêm định nghĩa dịch vụ vào tệp 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>