WorkManager ist eine Bibliothek zum Planen und Ausführen von zurückgestellten Hintergrundarbeiten. in Android. Es wird als Ersatz für Firebase JobDispatcher empfohlen. Die In der folgenden Anleitung erfahren Sie, wie Sie Firebase JobDispatcher-Implementierung in WorkManager.
Gradle einrichten
Um die WorkManager-Bibliothek in Ihr Android-Projekt zu importieren, fügen Sie den Abhängigkeiten in Erste Schritte mit WorkManager
Vom JobService zu Workern
FirebaseJobDispatcher
verwendet eine abgeleitete Klasse von
JobService
als Einstiegspunkt für die Definition der
zu erledigenden Arbeit dienen. Sie könnten
JobService
direkt verwenden oder
SimpleJobService
Ein JobService
sieht in etwa so aus:
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?" } }
Wenn Sie SimpleJobService
verwenden, haben Sie onRunJob()
überschrieben.
was einen @JobResult int
-Typ zurückgibt.
Der Hauptunterschied besteht darin, wenn Sie JobService
direkt verwenden, onStartJob()
wird im Hauptthread aufgerufen, und es liegt in der Verantwortung der App, das
mit einem Hintergrund-Thread arbeiten. Wenn Sie jedoch
SimpleJobService
, ist dieser Dienst für die Ausführung Ihrer Arbeit auf einem
im Hintergrund.
WorkManager hat ähnliche Konzepte. Die grundlegende Arbeitseinheit in WorkManager ist
ListenableWorker
. Es gibt
auch andere nützliche Untertypen von Workern,
Worker
,
RxWorker
und CoroutineWorker
(wenn
mit Kotlin-Koroutinen).
JobService wird einem ListenableWorker zugeordnet
Wenn Sie JobService
direkt verwenden, ist der Worker, dem sie zugeordnet ist, ein
ListenableWorker
. Wenn Sie SimpleJobService
verwenden, sollten Sie
Worker
.
Wir verwenden das obige Beispiel (MyJobService
) und sehen uns an, wie wir es konvertieren können.
zu einem ListenableWorker
.
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. } }
Die Grundeinheit in WorkManager ist ein ListenableWorker
. Genau wie
JobService.onStartJob()
, startWork()
wird im Hauptthread aufgerufen. Hier
MyWorker
implementiert ListenableWorker
und gibt eine Instanz von
ListenableFuture
,
Damit wird der Abschluss der Arbeit asynchron signalisiert. Sie sollten Ihre
eigene Threading-Strategie.
ListenableFuture
gibt hier schließlich einen ListenableWorker.Result
-Typ zurück.
Result.success()
, Result.success(Data outputData)
,
Result.retry()
, Result.failure()
oder Result.failure(Data outputData)
. Für
Weitere Informationen finden Sie auf der Referenzseite für
ListenableWorker.Result
onStopped()
wird aufgerufen, um zu signalisieren, dass die ListenableWorker
anhalten muss,
weil die Einschränkungen nicht mehr erfüllt werden (z. B. weil der
nicht mehr verfügbar ist oder weil eine WorkManager.cancel…()
-Methode
aufgerufen. onStopped()
kann auch aufgerufen werden, wenn das Betriebssystem beschließt,
funktionieren könnte.
SimpleJobService wird Worker zugeordnet
Bei Verwendung von SimpleJobService
sieht der obige Worker so aus:
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. } }
Hier gibt doWork()
eine Instanz von ListenableWorker.Result
zurück, um die Arbeit zu signalisieren.
synchron abgeschlossen werden. Das ähnelt der Methode SimpleJobService
, bei der
Jobs in einem Hintergrundthread.
JobBuilder ordnet WorkRequest zu
FirebaseJobBuilder verwendet Job.Builder
, um Job
-Metadaten darzustellen. WorkManager
verwendet WorkRequest
, um diese Rolle zu füllen.
In WorkManager gibt es zwei WorkRequest
-Typen:
OneTimeWorkRequest
und
PeriodicWorkRequest
Wenn Sie derzeit Job.Builder.setRecurring(true)
verwenden, sollten Sie
eine neue PeriodicWorkRequest
erstellen. Andernfalls sollten Sie
OneTimeWorkRequest
Sehen wir uns an, was die Planung einer komplexen Job
mit FirebaseJobDispatcher
Beispiel:
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);
Um dies mit WorkManager zu erreichen, müssen Sie Folgendes tun:
- Erstellt Eingabedaten, die als Eingabe für
Worker
verwendet werden können. - Erstellen Sie eine
WorkRequest
mit den Eingabedaten und Einschränkungen, die den ähneln. oben fürFirebaseJobDispatcher
definiert. - Füge
WorkRequest
in die Warteschlange ein.
Eingaben für den Worker einrichten
FirebaseJobDispatcher
verwendet eine Bundle
, um Eingabedaten an JobService
zu senden.
In WorkManager wird stattdessen Data
verwendet. Also
Daraus ergibt sich Folgendes:
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();
Einschränkungen für den Worker einrichten
FirebaseJobDispatcher
verwendet
Job.Builder.setConstaints(...)
um Einschränkungen für Jobs einzurichten. WorkManager verwendet
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();
WorkRequest erstellen (einmalig oder regelmäßig)
Zum Erstellen von OneTimeWorkRequest
- und PeriodicWorkRequest
-Elementen sollten Sie Folgendes verwenden:
OneTimeWorkRequest.Builder
und PeriodicWorkRequest.Builder
.
Um eine OneTimeWorkRequest
zu erstellen, die dem obigen Job
ähnelt, müssen Sie
Gehen Sie so vor:
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();
Der Hauptunterschied besteht darin, dass die Jobs von WorkManager wird Ihr Gerät automatisch neu gestartet.
Wenn Sie eine PeriodicWorkRequest
erstellen möchten, gehen Sie in etwa so vor:
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();
Aufgaben planen
Nachdem Sie nun eine Worker
und eine WorkRequest
definiert haben, können Sie
um die Arbeit zu planen.
Jede mit FirebaseJobDispatcher
definierte Job
hatte eine tag
, die für folgende Aktionen verwendet wurde:
ein Job
eindeutig identifiziert. Außerdem konnte die Anwendung damit feststellen,
den Planer, wenn diese Instanz einer Job
eine vorhandene Kopie der
Job
durch Aufrufen von setReplaceCurrent
.
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);
Wenn Sie WorkManager verwenden,
enqueueUniqueWork()
und enqueueUniquePeriodicWork()
API (bei Verwendung einer
OneTimeWorkRequest
bzw. PeriodicWorkRequest
). Weitere Informationen
finden Sie auf den Referenzseiten der
WorkManager.enqueueUniqueWork()
und WorkManager.enqueueUniquePeriodicWork()
.
Dies sieht ungefähr so aus:
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);
Aufgabe wird abgebrochen
Mit FirebaseJobDispatcher
können Sie eine Arbeit stornieren mit:
Kotlin
dispatcher.cancel("my-unique-tag")
Java
dispatcher.cancel("my-unique-tag");
Mit WorkManager können Sie Folgendes verwenden:
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 wird initialisiert
WorkManager initialisiert sich in der Regel mit einem ContentProvider
.
Wenn Sie mehr Kontrolle darüber benötigen, wie WorkManager die Arbeit organisiert und plant, können Sie
können die WorkManager-Konfiguration und -Initialisierung anpassen.