سلسلة المحادثات في ListenableWorker

في بعض الحالات، قد تحتاج إلى توفير استراتيجية مخصّصة لسلاسل المحادثات. بالنسبة على سبيل المثال، قد تحتاج إلى التعامل مع عملية غير متزامنة قائمة على معاودة الاتصال. يدعم WorkManager حالة الاستخدام هذه مع ListenableWorker ListenableWorker هي واجهة برمجة التطبيقات الأساسية الخاصة بالمشغّل، Worker, CoroutineWorker، أمّا RxWorker، فتكون جميعها من هذا الصف. حاسمة لا ترسِل ميزة "ListenableWorker" إلا إشارات بدء العمل وإيقافه ومغادرته. فإن سلسلة التعليمات متروكة لك بالكامل. يتم استدعاء إشارة بدء العمل على لذا، من المهم جدًا أن تنتقل إلى سلسلة التعليمات في الخلفية اختياره يدويًا.

الطريقة التجريدية ListenableWorker.startWork() تعرض الخطأ ListenableFuture من Result حاسمة ListenableFuture هي واجهة بسيطة، وهي Future التي توفّر وظيفة إرفاق أدوات معالجة الأحداث واستثناءات النشر. في جلسة المعمل، startWork، ومن المتوقع إرجاع ListenableFuture، والتي سيتم الضبط على Result للعملية بعد اكتمالها. يمكنك إنشاء ListenableFuture أمثلة بإحدى طريقتين:

  1. إذا كنت تستخدم Java، يمكنك استخدام 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، ما عليك سوى إضافة أداة استماع الإلغاء، على النحو التالي:

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 بعملية محدّدة باستخدام وسيطتين إضافيتين. التي تقدمها كجزء من بيانات الإدخال عند إنشاء طلب العمل: 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>

نماذج