Ich rufe scheduleWork() in onCreate() von meinen Application Klasse. Sogar ich kann überprüfen, ob mein Dienst ausgeführt wird oder nicht diese Methode. Aber ich möchte WorkManager nicht planen, wenn es bereits geplant ist, um Inkonsistenzen in der geplanten Zeit zu beseitigen.
Wie
if(!workManagerIsScheduled())
{
scheduleWork();
}
Irgendwelche Lösungen?
Sie können den Status der Arbeitsanfrage abrufen … zur Überprüfung
– Mann
31. Juli 2018 um 11:55 Uhr
Hast du das versucht?
– Mann
31. Juli 2018 um 12:00 Uhr
Siehe Antwort @Man
– Khemraj Sharma
31. Juli 2018 um 12:11 Uhr
Es ist nicht erforderlich zu prüfen, ob Worker bereits ausgeführt wird, da Sie instance.enqueueUniquePeriodicWork() mit ‘ExistingPeriodicWorkPolicy.KEEP’ verwenden. Es wird die neue PeriodicWorkRequest nur ausführen, wenn es keine ausstehende Arbeit gibt, die mit uniqueWorkName gekennzeichnet ist.
– Rai_Gaurav
31. Juli 2018 um 12:11 Uhr
„ExistingPeriodicWorkPolicy.KEEP“ ist für eine bestimmte Aufgabe, nicht für die Arbeit. Wenn ein Dienst seine Arbeit erledigt, hält dieses Flag den Dienst am Laufen, bis er seine Arbeit beendet hat.
– Khemraj Sharma
31. Juli 2018 um 12:13 Uhr
Khemraj Sharma
Aktualisieren
Wenn Sie den bereits ausgeführten Arbeitsmanager überprüfen müssen, nur weil Sie keine doppelten Arbeiten wünschen. Sie können einfach verwenden enqueueUniquePeriodicWork()
Mit dieser Methode können Sie eine PeriodicWorkRequest mit eindeutigem Namen in die Warteschlange einreihen, wobei jeweils nur eine PeriodicWorkRequest mit einem bestimmten Namen aktiv sein kann. Beispielsweise möchten Sie möglicherweise, dass nur ein Synchronisierungsvorgang aktiv ist. Wenn eines aussteht, können Sie es ausführen lassen oder durch Ihre neue Arbeit ersetzen.
Sie müssen sich also keine Gedanken über Doppelarbeit bei Werken machen.
Es wird zurückkehren true wenn etwas von seiner Aufgabe ist RUNNING oder ENQUEUED.
Beispielcode
public static final String TAG_MY_WORK = "mywork";
if(!isWorkScheduled(TAG_MY_WORK)) { // check if your work is not already scheduled
scheduleWork(TAG_MY_WORK); // schedule your work
}
public static void scheduleWork(String tag) {
PeriodicWorkRequest.Builder photoCheckBuilder =
new PeriodicWorkRequest.Builder(WorkManagerService.class, TIME_INTERVAL_IN_SECONDS,
TimeUnit.SECONDS);
PeriodicWorkRequest photoCheckWork = photoCheckBuilder.build();
WorkManager instance = WorkManager.getInstance();
instance.enqueueUniquePeriodicWork(tag, ExistingPeriodicWorkPolicy.KEEP , photoCheckWork);
}
Hallo Khemraj, Ihre Lösung gibt mir diese Art von Fehler androidx.work.impl.utils.futures.SettableFuture kann nicht in android.arch.lifecycle.LiveData umgewandelt werden Es kann nicht umgewandelt werden LiveData> statuses = instance.getStatusesByTag( Schild);
– Rahul Patil
3. November 2018 um 7:12 Uhr
Wenn Sie den Status der Livedaten abrufen möchten, müssen Sie gemäß der neuen API „getStatusesByTag(tag)“ in „getStatusesByTagLiveData(tag)“ ändern.
– Saurabh
6. November 2018 um 6:14 Uhr
Wie wäre es mit State.BLOCKED ?. Warum wird es nicht zur Überprüfung verwendet? developer.android.com/topic/libraries/architecture/workmanager/…. Es erklärt, dass eine Aufgabe darauf wartet, dass andere Aufgaben beendet werden, die der Reihe nach ausgeführt werden sollen. Idealerweise sollten wir nicht verwenden !state.isFinished() um alle Tasks zu überprüfen, die sich noch in der Warteschlange befinden oder ausgeführt werden oder auf die Ausführung warten.
– Sreejith B. Naick
28. Mai 2019 um 14:58 Uhr
Beim Überprüfen von instance.getWorkInfosByTag(tag) wird immer eine leere Liste zurückgegeben, daher habe ich instance.getWorkInfosForUniqueWork(tag) verwendet und funktioniert in Abhängigkeiten -> Implementierung “androidx.work:work-runtime:2.2.0”
– Sarah Kumar
23. November 2019 um 13:19 Uhr
Du solltest benutzen running |= state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED; Andernfalls, running wird den Wert des letzten haben workInfo
– Schild
5. Februar 2020 um 12:23 Uhr
aus 1.0.0-alpha11 zusammen mit vielen Dingen Arbeitsstatus funktioniert nicht, es wurde entfernt und es ist eine bahnbrechende Änderung. Überprüfen Sie die Versionshinweise
WorkStatus wurde in WorkInfo umbenannt. Alle entsprechenden getStatus-Methodenvarianten wurden in die entsprechenden getWorkInfo-Varianten umbenannt. Dies ist eine bahnbrechende Änderung.
nach update auf alpha11 ist der funktionierende code.
Abgesehen von einigen Umgestaltungen, um irreführende Mehrfachrückgaben zu vermeiden, liegt der Fehler in dieser Zeile
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
Wenn Sie diese Zeile verwenden, erhalten Sie nur die zuletzt ausgewertete running. Ein Kommentar schlägt vor, den Operator zu verwenden =| stattdessen. Selbst wenn das Ergebnis korrekt sein sollte, wird der Code unklar und (leicht) suboptimal sein. | ist ein bitweiser Operator und || ist ein logischer Operator. Die Operation, die wir ausführen möchten, ist logisch, nicht bitweise. Bei booleschen Werten | und || geben das gleiche Ergebnis, aber nur || ist eine Abkürzung, was in unserem Fall das beabsichtigte Verhalten ist.
Dieser Code funktioniert mindestens für WorkManager 2.5.0 und 2.6.0.
David Sucharda
Seit dem 11. Oktober (2018) können Sie verwenden Hörbare Zukunft Anstatt von SynchronousWorkManager was entfernt wurde:
Mit ListenableFutures können Sie jetzt synchron abrufen und beobachten. Beispielsweise wurde WorkManager.enqueue() verwendet, um void zurückzugeben; es gibt jetzt ein ListenableFuture zurück. Sie können ListenableFuture.addListener(Runnable, Executor) oder ListenableFuture.get() aufrufen, um Code auszuführen, sobald der Vorgang abgeschlossen ist.
Eine weitere Option kann die Verwendung sein ListenableWorker:
Eine Klasse, die in WorkManager asynchron arbeiten kann. In den meisten Fällen empfehlen wir die Verwendung von Worker, das eine einfache synchrone API bietet, die auf einem vordefinierten Hintergrundthread ausgeführt wird.
Es kehrt zurück Hörbare Zukunft nachdem Sie die Funktion startWork() aufgerufen haben.
Ich habe die Antwort in diesem Beitrag gefunden und einige Änderungen vorgenommen.
In meinem Projekt; Ich sende alle 15 Minuten Standortinformationen an den Server. Und ich möchte WorkManager nicht planen, wenn es bereits geplant ist.
// Fırst I'm creating workRequest here.
private void createWorkRequest() {
Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder
(LocationWorker.class, 15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build();
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork("sendLocation", ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest);
}
// Then i'm learning the state of Work
private WorkInfo.State getStateOfWork() {
try {
if (WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation").get().size() > 0) {
return WorkManager.getInstance(this).getWorkInfosForUniqueWork("sendLocation")
.get().get(0).getState();
// this can return WorkInfo.State.ENQUEUED or WorkInfo.State.RUNNING
// you can check all of them in WorkInfo class.
} else {
return WorkInfo.State.CANCELLED;
}
} catch (ExecutionException e) {
e.printStackTrace();
return WorkInfo.State.CANCELLED;
} catch (InterruptedException e) {
e.printStackTrace();
return WorkInfo.State.CANCELLED;
}
}
// If work not ( ENQUEUED and RUNNING ) i'm running the work.
// You can check with other ways. It's up to you.
private void startServerWork() {
if (getStateOfWork() != WorkInfo.State.ENQUEUED && getStateOfWork() != WorkInfo.State.RUNNING) {
createWorkRequest();
Log.wtf("startLocationUpdates", ": server started");
} else {
Log.wtf("startLocationUpdates", ": server already working");
}
}
Ich denke, wir sollten alle sechs Status von WorkRequest by UniqueWorkName überprüfen. Wenn die Arbeitsanfrage in einen der Bundesstaaten fällt, sollten wir sie bereits als geplant markieren. Sie können auch einige Status in Ihrem Fall entfernen, um Ihre geschäftlichen Anforderungen zu erfüllen.
private fun isWorkEverScheduledBefore(context: Context, tag: String): Boolean {
val instance = WorkManager.getInstance(context)
val statuses: ListenableFuture<List<WorkInfo>> = instance.getWorkInfosForUniqueWork(tag)
var workScheduled = false
statuses.get()?.let {
for (workStatus in it) {
workScheduled = (
workStatus.state == WorkInfo.State.ENQUEUED
|| workStatus.state == WorkInfo.State.RUNNING
|| workStatus.state == WorkInfo.State.BLOCKED
|| workStatus.state.isFinished // It checks SUCCEEDED, FAILED, CANCELLED already
)
}
}
return workScheduled
}
10427300cookie-checkÜberprüfen Sie, ob WorkManager bereits eingeplant istyes
Sie können den Status der Arbeitsanfrage abrufen … zur Überprüfung
– Mann
31. Juli 2018 um 11:55 Uhr
Hast du das versucht?
– Mann
31. Juli 2018 um 12:00 Uhr
Siehe Antwort @Man
– Khemraj Sharma
31. Juli 2018 um 12:11 Uhr
Es ist nicht erforderlich zu prüfen, ob Worker bereits ausgeführt wird, da Sie instance.enqueueUniquePeriodicWork() mit ‘ExistingPeriodicWorkPolicy.KEEP’ verwenden. Es wird die neue PeriodicWorkRequest nur ausführen, wenn es keine ausstehende Arbeit gibt, die mit uniqueWorkName gekennzeichnet ist.
– Rai_Gaurav
31. Juli 2018 um 12:11 Uhr
„ExistingPeriodicWorkPolicy.KEEP“ ist für eine bestimmte Aufgabe, nicht für die Arbeit. Wenn ein Dienst seine Arbeit erledigt, hält dieses Flag den Dienst am Laufen, bis er seine Arbeit beendet hat.
– Khemraj Sharma
31. Juli 2018 um 12:13 Uhr