Firebase JobDispatcher'dan WorkManager'a taşıma

WorkManager, ertelenebilir arka plan çalışmalarının planlanması ve yürütülmesi için kullanılan bir kitaplıktır bazı yolları da görmüştük. Firebase JobDispatcher için önerilen alternatiftir. İlgili içeriği oluşturmak için kullanılan Aşağıdaki rehber, Firebase'inizi taşıma sürecinde size yol gösterecektir WorkManager'a JobDispatcher uygulaması.

Gradle kurulumu

WorkManager kitaplığını Android projenize aktarmak için bağımlılıklarını WorkManager'ı kullanmaya başlama.

JobService'ten çalışanlara

FirebaseJobDispatcher şunun bir alt sınıfını kullanır: JobService yapılması gereken işleri tanımlamak için bir giriş noktası olarak kullanılmaktadır. En çok doğrudan JobService veya SimpleJobService

JobService aşağıdaki gibi görünür:

Kotlin

import com.firebase.jobdispatcher.JobParameters
import com.firebase.jobdispatcher.JobService

class MyJobService : JobService() {
    override fun onStartJob(job: JobParameters): Boolean {
        // Do some work here
        return false // Answers the question: "Is there still work going on?"
    }
    override fun onStopJob(job: JobParameters): Boolean {
        return false // Answers the question: "Should this job be retried?"
    }
}

Java

import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters job) {
        // Do some work here

        return false; // Answers the question: "Is there still work going on?"
    }

    @Override
    public boolean onStopJob(JobParameters job) {
        return false; // Answers the question: "Should this job be retried?"
    }
}

SimpleJobService kullanıyorsanız onRunJob() politikasını geçersiz kılarsınız. @JobResult int türü döndürür.

Aradaki temel fark, JobService ürününü doğrudan (onStartJob()) kullanmanızdır. ana iş parçacığında çağrılır ve arka plandaki ileti dizisinde çalışır. Diğer yandan SimpleJobService, bu hizmet bir web sitesindeki çalışmanızı yürütmekten arka plan ileti dizisi.

WorkManager'da benzer kavramlar vardır. WorkManager'ın temel çalışma birimi ListenableWorker. Her biri 100'den az gösterim alan diğer yararlı alt türleri de vardır. Worker RxWorker ve CoroutineWorker ( kotlin eş yordamlarını kullanarak).

JobService, bir ListenableWorker ile eşlenir

Doğrudan JobService kullanıyorsanız eşlendiği çalışan bir ListenableWorker. SimpleJobService kullanıyorsanız Bunun yerine Worker.

Yukarıdaki örneği (MyJobService) kullanıp bunu nasıl dönüştürebileceğimize bakalım. ListenableWorker olarak değiştirdik.

Kotlin

import android.content.Context
import androidx.work.ListenableWorker
import androidx.work.ListenableWorker.Result
import androidx.work.WorkerParameters
import com.google.common.util.concurrent.ListenableFuture

class MyWorker(appContext: Context, params: WorkerParameters) :
    ListenableWorker(appContext, params) {

    override fun startWork(): ListenableFuture<ListenableWorker.Result> {
        // Do your work here.
        TODO("Return a ListenableFuture<Result>")
    }

    override fun onStopped() {
        // Cleanup because you are being stopped.
    }
}

Java

import android.content.Context;
import androidx.work.ListenableWorker;
import androidx.work.ListenableWorker.Result;
import androidx.work.WorkerParameters;
import com.google.common.util.concurrent.ListenableFuture;

class MyWorker extends ListenableWorker {

  public MyWorker(@NonNull Context appContext, @NonNull WorkerParameters params) {
    super(appContext, params);
  }

  @Override
  public ListenableFuture<ListenableWorker.Result> startWork() {
    // Do your work here.
    Data input = getInputData();

    // Return a ListenableFuture<>
  }

  @Override
  public void onStopped() {
    // Cleanup because you are being stopped.
  }
}

WorkManager'daki temel çalışma birimi ListenableWorker'dir. Aynı JobService.onStartJob(), startWork(), ana iş parçacığında çağrılıyor. Burası MyWorker, ListenableWorker öğesini uygular ve şunun bir örneğini döndürür: ListenableFuture, İşin tamamlanma durumunu eşzamansız olarak belirtmek için kullanılır. size özel bir ileti dizisi stratejisi oluşturduk.

Buradaki ListenableFuture, sonunda ListenableWorker.Result türünü döndürür. Bu değer Result.success(), Result.success(Data outputData), Result.retry(), Result.failure() veya Result.failure(Data outputData). Örneğin, daha fazla bilgi için referans sayfasına bakın; ListenableWorker.Result.

onStopped(), ListenableWorker öğesinin durması gerektiğini belirtmek için çağrılır, Bunun nedeni kısıtlamaların artık karşılanmamasıdır (örneğin, ağı artık kullanılamadığından) veya bir WorkManager.cancel…() yöntemi çağrıldı. onStopped(), işletim sistemi cihazınızı kapatmaya karar verirse bir sebepten ötürü zorlanmasıdır.

SimplejobService bir Çalışan ile eşlenir

SimpleJobService kullanılırken yukarıdaki çalışan aşağıdaki gibi görünür:

Kotlin

import android.content.Context;
import androidx.work.Data;
import androidx.work.ListenableWorker.Result;
import androidx.work.Worker;
import androidx.work.WorkerParameters;


class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        TODO("Return a Result")
    }

    override fun onStopped() {
        super.onStopped()
        TODO("Cleanup, because you are being stopped")
    }
}

Java

import android.content.Context;
import androidx.work.Data;
import androidx.work.ListenableWorker.Result;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

class MyWorker extends Worker {

  public MyWorker(@NonNull Context appContext, @NonNull WorkerParameters params) {
    super(appContext, params);
  }

  @Override
  public Result doWork() {
    // Do your work here.
    Data input = getInputData();

    // Return a ListenableWorker.Result
    Data outputData = new Data.Builder()
        .putString(Key, value)
        .build();
    return Result.success(outputData);
  }

  @Override
  public void onStopped() {
    // Cleanup because you are being stopped.
  }
}

Burada doWork(), işin sinyalini vermek için ListenableWorker.Result öğesinin bir örneğini döndürür eşzamanlı olarak tamamlayabilirsiniz. Bu, SimpleJobService programlarına benziyor. iş ilanlarına yazarlar.

JobBuilder, WorkRequest ile eşler

FirebasejobBuilder, Job meta verilerini göstermek için Job.Builder kullanır. İş Yöneticisi bu rolü doldurmak için WorkRequest kullanıyor.

WorkManager'da iki tür WorkRequest vardır: OneTimeWorkRequest ve PeriodicWorkRequest.

Şu anda Job.Builder.setRecurring(true) kullanıyorsanız yeni bir PeriodicWorkRequest oluşturun. Aksi takdirde OneTimeWorkRequest

FirebaseJobDispatcher için karmaşık bir Job planlamasının neden olabileceğine bakalım. gibi görünür:

Kotlin

val input: Bundle = Bundle().apply {
    putString("some_key", "some_value")
}

val job = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyService::class.java)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job
    .setRecurring(false)
    // don't persist past a device reboot
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)

    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(input)
    .build()

dispatcher.mustSchedule(job)

Java

Bundle input = new Bundle();
input.putString("some_key", "some_value");

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job
    .setRecurring(false)
    // don't persist past a device reboot
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
    // constraints that need to be satisfied for the job to run
    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(input)
    .build();

dispatcher.mustSchedule(myJob);

Bunu WorkManager ile yapmak için şunları yapmanız gerekir:

  • Worker için giriş olarak kullanılabilecek giriş verileri oluşturun.
  • Giriş verileri ve kısıtlamalara benzer kısıtlamalara sahip bir WorkRequest oluşturun yukarıda FirebaseJobDispatcher için tanımlanmıştır.
  • WorkRequest öğesini sıraya alın.

Çalışan için girişleri ayarlama

FirebaseJobDispatcher, giriş verilerini JobService cihazına göndermek için bir Bundle kullanır. WorkManager, bunun yerine Data kullanır. ODK şu hale gelir:

Kotlin

import androidx.work.workDataOf
val data = workDataOf("some_key" to "some_val")

Java

import androidx.work.Data;
Data input = new Data.Builder()
    .putString("some_key", "some_value")
    .build();

Çalışan İçin Kısıtlamaları Ayarlama

FirebaseJobDispatcher kullanımları Job.Builder.setConstaints(...) bu sayede işlerde kısıtlamalar oluşturabilirsiniz. WorkManager, Bunun yerine Constraints.

Kotlin

import androidx.work.*

val constraints: Constraints = Constraints.Builder().apply {
    setRequiredNetworkType(NetworkType.CONNECTED)
    setRequiresCharging(true)
}.build()

Java

import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;

Constraints constraints = new Constraints.Builder()
    // The Worker needs Network connectivity
    .setRequiredNetworkType(NetworkType.CONNECTED)
    // Needs the device to be charging
    .setRequiresCharging(true)
    .build();

İş İsteği Oluşturma (Tek Seferlik veya Periyodik)

OneTimeWorkRequest ve PeriodicWorkRequest oluşturmak için OneTimeWorkRequest.Builder ve PeriodicWorkRequest.Builder.

Yukarıdakine benzer bir OneTimeWorkRequest oluşturmak için Job şunları yapın:

Kotlin

import androidx.work.*
import java.util.concurrent.TimeUnit

val constraints: Constraints = TODO("Define constraints as above")
val request: OneTimeWorkRequest =
     // Tell which work to execute
     OneTimeWorkRequestBuilder<MyWorker>()
         // Sets the input data for the ListenableWorker
        .setInputData(input)
        // If you want to delay the start of work by 60 seconds
        .setInitialDelay(60, TimeUnit.SECONDS)
        // Set a backoff criteria to be used when retry-ing
        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30000, TimeUnit.MILLISECONDS)
        // Set additional constraints
        .setConstraints(constraints)
        .build()

Java

import androidx.work.BackoffCriteria;
import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OneTimeWorkRequest.Builder;
import androidx.work.Data;

// Define constraints (as above)
Constraints constraints = ...
OneTimeWorkRequest request =
    // Tell which work to execute
    new OneTimeWorkRequest.Builder(MyWorker.class)
        // Sets the input data for the ListenableWorker
        .setInputData(inputData)
        // If you want to delay the start of work by 60 seconds
        .setInitialDelay(60, TimeUnit.SECONDS)
        // Set a backoff criteria to be used when retry-ing
        .setBackoffCriteria(BackoffCriteria.EXPONENTIAL, 30000, TimeUnit.MILLISECONDS)
        // Set additional constraints
        .setConstraints(constraints)
        .build();

Buradaki temel fark, WorkManager'ın işlerinin her zaman otomatik olarak yeniden başlatmasını sağlar.

PeriodicWorkRequest oluşturmak istiyorsanız aşağıdaki gibi bir işlem yapmanız gerekir:

Kotlin

val constraints: Constraints = TODO("Define constraints as above")
val request: PeriodicWorkRequest =
PeriodicWorkRequestBuilder<MyWorker>(15, TimeUnit.MINUTES)
    // Sets the input data for the ListenableWorker
    .setInputData(input)
    // Other setters
    .build()

Java

import androidx.work.BackoffCriteria;
import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.PeriodicWorkRequest.Builder;
import androidx.work.Data;

// Define constraints (as above)
Constraints constraints = ...

PeriodicWorkRequest request =
    // Executes MyWorker every 15 minutes
    new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
        // Sets the input data for the ListenableWorker
        .setInputData(input)
        . // other setters (as above)
        .build();

İşi planlama

Artık bir Worker ve WorkRequest tanımladığınıza göre, zaman çizelgesine uyacağınızı ifade etmelisiniz.

FirebaseJobDispatcher ile tanımlanan her Job, şu amaçla kullanılan bir tag içeriyordu: Job öğelerini benzersiz olarak tanımlayabilirsiniz. Ayrıca uygulamanın bu özelliği kullanarak Job örneğinin mevcut bir kopyasının yerine geçecekse planlayıcıya setReplaceCurrent numaralı telefonu arayarak Job.

Kotlin

val job = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyService::class.java)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // don't overwrite an existing job with the same tag
    .setRecurring(false)
    // Other setters...
    .build()

Java

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // other setters
    // ...

dispatcher.mustSchedule(myJob);

WorkManager'ı kullanırken aynı sonucu enqueueUniqueWork() ve enqueueUniquePeriodicWork() API'leri ( sırasıyla OneTimeWorkRequest ve PeriodicWorkRequest). Daha fazla daha fazla bilgi için referans sayfalarına WorkManager.enqueueUniqueWork() ve WorkManager.enqueueUniquePeriodicWork().

Aşağıdaki gibi görünür:

Kotlin

import androidx.work.*

val request: OneTimeWorkRequest = TODO("A WorkRequest")
WorkManager.getInstance(myContext)
    .enqueueUniqueWork("my-unique-name", ExistingWorkPolicy.KEEP, request)

Java

import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;

OneTimeWorkRequest workRequest = // a WorkRequest;
WorkManager.getInstance(myContext)
    // Use ExistingWorkPolicy.REPLACE to cancel and delete any existing pending
    // (uncompleted) work with the same unique name. Then, insert the newly-specified
    // work.
    .enqueueUniqueWork("my-unique-name", ExistingWorkPolicy.KEEP, workRequest);

İş iptal ediliyor

FirebaseJobDispatcher ile çalışmanızı iptal etmek için şunları kullanabilirsiniz:

Kotlin

dispatcher.cancel("my-unique-tag")

Java

dispatcher.cancel("my-unique-tag");

WorkManager'ı kullanırken şunları kullanabilirsiniz:

Kotlin

import androidx.work.WorkManager
WorkManager.getInstance(myContext).cancelUniqueWork("my-unique-name")

Java

import androidx.work.WorkManager;
WorkManager.getInstance(myContext).cancelUniqueWork("my-unique-name");

WorkManager'ı başlatma

WorkManager genellikle bir ContentProvider kullanarak kendini başlatır. WorkManager'ın nasıl düzenlediği ve programladığı konusunda daha fazla kontrole ihtiyacınız varsa WorkManager yapılandırmasını ve başlatmayı özelleştirebilirsiniz.