การจัดชุดข้อความใน ListenableWorker

ในบางสถานการณ์ คุณอาจต้องระบุกลยุทธ์การแยกชุดข้อความที่กำหนดเอง สำหรับ ตัวอย่างเช่น คุณอาจต้องจัดการการทำงานไม่พร้อมกันในลักษณะ Callback WorkManager รองรับกรณีการใช้งานนี้กับ ListenableWorker ListenableWorker เป็น API ผู้ปฏิบัติงานขั้นพื้นฐานที่สุด Worker, CoroutineWorker และ RxWorker ทุกคนจะได้มาจากชั้นเรียนนี้ ต ListenableWorker จะส่งสัญญาณเฉพาะเมื่องานควรเริ่มและหยุด รวมถึงออก ชุดข้อความขึ้นอยู่กับคุณ สัญญาณเริ่มต้นงานจะเรียกใช้บน ดังนั้นคุณจึงต้องไปที่ ชุดข้อความที่พื้นหลังของ ด้วยตนเอง

กระบวนการเชิงนามธรรม ListenableWorker.startWork() แสดงผล ListenableFuture ของ ResultListenableFuture เป็นอินเทอร์เฟซขนาดเล็ก โดยเป็น Future ที่ให้ ฟังก์ชันสำหรับการแนบ Listener และการเผยแพร่ข้อยกเว้น ใน startWork คุณควรแสดงผล ListenableFuture ซึ่งคุณ จะกำหนดด้วยการดำเนินการ Result เมื่อเสร็จสิ้น คุณสามารถสร้าง ListenableFuture อินสแตนซ์ด้วยวิธีใดวิธีหนึ่งใน 2 วิธีนี้

  1. หากคุณใช้ Guava ให้ใช้ ListeningExecutorService
  2. หรือไม่เช่นนั้น ให้ใส่ councurrent-futures ในไฟล์ Gradle และใช้ 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;
        });
    }
}

สิ่งที่จะเกิดขึ้นหากงานของคุณ หยุดแล้ว ListenableFuture ของ ListenableWorker จะถูกยกเลิกเสมอเมื่องาน คาดว่าจะหยุด ในการใช้ CallbackToFutureAdapter คุณเพียงแค่ต้องเพิ่ม Listener การยกเลิก ดังนี้

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;
        });
    }
}

การเรียกใช้ ListenableWorker ในกระบวนการอื่น

นอกจากนี้คุณยังเชื่อมโยงผู้ปฏิบัติงานกับกระบวนการที่ต้องการได้โดยใช้ RemoteListenableWorker การใช้งาน ListenableWorker

RemoteListenableWorker เชื่อมโยงกับกระบวนการเฉพาะที่มีอาร์กิวเมนต์เกิน 2 รายการ ที่คุณให้ไว้เป็นส่วนหนึ่งของข้อมูลที่ป้อนเมื่อสร้างคำของาน 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>

ตัวอย่าง