ListenableWorker'da mesaj dizisi oluşturma

Belirli durumlarda, özel bir ileti dizisi stratejisi sağlamanız gerekebilir. Örneğin, geri çağırmaya dayalı eşzamansız bir işlem gerçekleştirmeniz gerekebilir. WorkManager, bu kullanım alanını ListenableWorker ile destekler. ListenableWorker en temel çalışan API'dir. Worker, CoroutineWorker ve RxWorker hepsi bu sınıftan türetilir. ListenableWorker, yalnızca işin ne zaman başlayıp durması gerektiğini belirtir ve iş parçacığını tamamen size bırakır. İş başlatma sinyali ana iş parçacığında çağrılır. Bu nedenle, seçtiğiniz arka plan ileti dizisine manuel olarak gitmeniz çok önemlidir.

Soyut yöntem ListenableWorker.startWork(), Result ListenableFuture değerini döndürür. ListenableFuture, basit bir arayüzdür: İşleyici ekleme ve istisnaları yayma işlevi sağlayan bir Future'dir. startWork yönteminde, bir ListenableFuture döndürmeniz gerekir. Bu değer, tamamlandığında işlemin Result değeriyle ayarlanır. Aşağıdaki iki yöntemden birini kullanarak ListenableFuture örnekleri oluşturabilirsiniz:

  1. Guava kullanıyorsanız ListeningExecutorService kullanın.
  2. Aksi takdirde, councurrent-futures öğesini gradle dosyanıza ekleyin ve CallbackToFutureAdapter kullanın.

Eşzamansız geri çağırmaya dayalı bazı çalışmalar yürütmek isterseniz şunun gibi bir şey yaparsınız:

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

Çalışmanız durdurursa ne olur? İşin durması beklendiğinde bir ListenableWorker ListenableFuture her zaman iptal edilir. CallbackToFutureAdapter kullanırken aşağıdaki gibi iptal işleyici eklemeniz gerekir:

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'ı farklı bir işlemde çalıştırma

Ayrıca, bir ListenableWorker uygulaması olan RemoteListenableWorker kullanarak bir çalışanı belirli bir sürece bağlayabilirsiniz.

RemoteListenableWorker, iş isteğini oluştururken giriş verileri kapsamında sağladığınız ek iki bağımsız değişkenle belirli bir sürece bağlanır: ARGUMENT_CLASS_NAME ve ARGUMENT_PACKAGE_NAME.

Aşağıdaki örnek, belirli bir sürece bağlı bir iş isteğinin oluşturulmasını göstermektedir:

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

Her RemoteWorkerService için AndroidManifest.xml dosyanıza bir hizmet tanımı da eklemeniz gerekir:

<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>

Sana Özel