Zarządzanie pracą

Po zdefiniowaniu Worker i WorkRequest, Ostatnią czynnością jest umieszczenie zadań w kolejce. Najprostszy sposób dodawania zadań do kolejki jest wywołanie metody enqueue() w WorkManager i przekazywaniu WorkRequest co chce zrobić.

Kotlin

val myWork: WorkRequest = // ... OneTime or PeriodicWork
WorkManager.getInstance(requireContext()).enqueue(myWork)

Java

WorkRequest myWork = // ... OneTime or PeriodicWork
WorkManager.getInstance(requireContext()).enqueue(myWork);

Zachowaj ostrożność podczas dodawania zadań do kolejki, aby uniknąć ich duplikowania. Aplikacja może na przykład próbować przesłać do usługi backendu co 24 godziny. Jeśli nie zachowasz ostrożności, to samo zadanie zostanie umieszczone w kolejce wiele razy, mimo że musi ono które można uruchomić tylko raz. Aby osiągnąć ten cel, możesz zaplanować wykonanie niepowtarzalnej pracy.

Wyjątkowa praca

Unikalna praca to potężna koncepcja, która gwarantuje, że dysponujesz tylko jednym wystąpienia pracy o określonej nazwie naraz. W przeciwieństwie do identyfikatorów, unikalne nazwy są zrozumiałe dla człowieka i określone przez dewelopera, a nie generowane automatycznie; przez WorkManagera. Nie podoba mi się tags, unikalny użytkownik są powiązane tylko z jedną instancją pracy.

Unikalną pracę można wykorzystać zarówno do zadań jednorazowych, jak i okresowych. Możesz utworzyć w zależności od tego, czy gdy planujesz zadanie cykliczne lub jednorazowe.

W obu przypadkach można użyć 3 argumentów:

  • uniqueWorkNameString służy do jednoznacznej identyfikacji utworu. użytkownika.
  • existingWorkPolicyenum, który informuje usługę WorkManager, co ma zrobić czy mamy już niedokończony łańcuch zadań o takiej unikalnej nazwie. Zobacz zasady rozwiązywania konfliktów.
  • workWorkRequest do zaplanowania.

Korzystając z tej możliwości, możemy rozwiązać wspomniany wcześniej zduplikowany problem z planowaniem.

Kotlin

val sendLogsWorkRequest =
       PeriodicWorkRequestBuilderS<endLogsWorker(>24, TimeUnit.HOURS)
           .setConstraints(Constraints.Builder()
               .setRequiresCharging(true)
               .build()
            )
           .build()
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
           "sendLogs",
           ExistingPeriodicWorkPolicy.KEEP,
           sendLogsWorkRequest
)

Java

PeriodicWorkRequest sendLogsWorkRequest = new
      PeriodicWorkRequest.Builder(SendLogsWorker.class, 24, TimeUnit.HOURS)
              .setConstraints(new Constraints.Builder()
              .setRequiresCharging(true)
          .build()
      )
     .build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
     "sendLogs",
     ExistingPeriodicWorkPolicy.KEEP,
     sendLogsWorkRequest);

Jeśli kod zostanie uruchomiony, gdy zadanie sendLogs jest już w kolejce, zadanie zostanie zachowane i nie zostanie dodane żadne nowe zadanie.

Unikalne sekwencje pracy mogą być też przydatne, jeśli musisz stopniowo tworzyć długie łańcucha zadań. Na przykład aplikacja do edycji zdjęć może pozwalać użytkownikom na cofanie długi łańcuch działań. Każda z tych operacji cofania może zająć trochę czasu, ale muszą być wykonywane we właściwej kolejności. W takim przypadku aplikacja może utwórz polecenie „cofnij” i w razie potrzeby dołączyć do łańcucha każdą operację cofania. Zobacz Łączenie zadań .

Zasady rozwiązywania konfliktów

Podczas planowania unikalnej pracy musisz poinformować WorkManagera, jakie działanie wykonać, gdy konflikt. Można to zrobić, dodając wartość wyliczeniową podczas umieszczania zadania w kolejce.

W przypadku pracy jednorazowej podajesz ExistingWorkPolicy, czyli obsługuje 4 opcje obsługi konfliktu.

  • Istniejące: REPLACE z nową pracą. Ta opcja powoduje anulowanie istniejącego zadania.
  • KEEP istniejących zadań oraz zignoruj nową pracę.
  • APPEND nowe zadanie na koniec istniejącej pracy. Te zasady spowodują, że Twoje nowe utwory będą łańcuch uruchomionej po zakończeniu pracy istniejącej.

Istniejący utwór staje się wymaganiem wstępnym dla nowego utworu. Jeśli dotychczasowy utwór zmieni się na CANCELLED lub FAILED, nowa praca będzie również CANCELLED lub FAILED. Jeśli chcesz, aby nowa praca była uruchamiana niezależnie od stanu istniejącej, użyj interfejsu APPEND_OR_REPLACE.

  • APPEND_OR_REPLACE działa podobnie do APPEND, z tym wyjątkiem, że nie jest zależne od warunek wstępny. Jeśli istniejące dzieło to CANCELLED lub FAILED, nowe zadanie nadal trwa.

W przypadku pracy z okresu możesz podać ExistingPeriodicWorkPolicy który obsługuje 2 opcje: REPLACE i KEEP. Te opcje działają tak samo .

Obserwowanie swojej pracy

W dowolnym momencie po dodaniu zadań do kolejki możesz sprawdzić ich stan, wysyłając zapytanie WorkManagera można użyć za pomocą instancji name, id lub powiązanej z nią tag.

Kotlin

// by id
workManager.getWorkInfoById(syncWorker.id) // ListenableFutureW<orkInfo<>/span>

// by name
workManager.getWorkInfosForUniqueWork("sync") // ListenableFutureL<istW<orkInfo<>/span>
>
// by tag
workManager.getWorkInfosByTag("syncTag") // ListenableFutureL<istW<orkInfo<>/span>
>

Java

// by id
workManager.getWorkInfoById(syncWorker.id); // ListenableFutureW<orkInfo<>/span>

// by name
workManager.getWorkInfosForUniqueWork("sync"); // ListenableFutureL<istW<orkInfo<>/span>
>
// by tag
workManager.getWorkInfosByTag("syncTag"); // ListenableFutureL<istW<orkInfo<>/span>
>

Zapytanie zwraca ListenableFuture obiektu WorkInfo, który zawiera id utworu, jego tagów, bieżące State oraz wszystkie dane wyjściowe ustaw przez Result.success(outputData).

Wariant LiveData każdego z parametrów pozwalają obserwować zmiany w WorkInfo przez rejestrację słuchaczem. Jeśli na przykład chcesz wyświetlać użytkownikowi wiadomość, gdy niektóre zadania zakończą się pomyślnie, możesz skonfigurować ustawienia w następujący sposób:

Kotlin

workManager.getWorkInfoByIdLiveData(syncWorker.id)
               .observe(viewLifecycleOwner) { workInfo -
>   if(workInfo?.state == WorkInfo.State.SUCCEEDED) {
       Snackbar.make(requireView(), 
      R.string.work_completed, Snackbar.LENGTH_SHORT)
           .show()
   }
}

Java

workManager.getWorkInfoByIdLiveData(syncWorker.id)
        .observe(getViewLifecycleOwner(), workInfo - >{
    if (workInfo.getState() != null 
&&            workInfo.getState() == WorkInfo.State.SUCCEEDED) {
        Snackbar.make(requireView(),
                    R.string.work_completed, Snackbar.LENGTH_SHORT)
                .show();
   }
});

Złożone zapytania służbowe

WorkManager w wersji 2.4.0 lub nowszej obsługuje złożone zapytania w przypadku zadań w kolejce za pomocą WorkQuery obiektów. WorkQuery obsługuje zapytania o pracę na podstawie kombinacji tagów, stanu i niepowtarzalnej nazwy utworu.

Z przykładu poniżej dowiesz się, jak znaleźć wszystkie tagi „syncTag”, który jest w stanie FAILED lub CANCELLED i ma unikalną nazwę utworu „preProcess” lub „sync”.

Kotlin

val workQuery = WorkQuery.Builder
       .fromTags(listOf("syncTag"))
       .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
       .addUniqueWorkNames(listOf("preProcess", "sync")
    )
   .build()

val workInfos: ListenableFutureL<istW<orkInfo >>= workManager.getWorkInfos(workQuery)

Java

WorkQuery workQuery = WorkQuery.Builder
       .fromTags(Arrays.asList("syncTag"))
       .addStates(Arrays.asList(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
       .addUniqueWorkNames(Arrays.asList("preProcess", "sync")
     )
    .build();

ListenableFutureL<istW<orkInfo >>workInfos = workManager.getWorkInfos(workQuery);

Każdy składnik (tag, stan lub nazwa) w elemencie WorkQuery jest AND-ed z prefiksem reszta. Każda wartość komponentu jest typu OR. Na przykład: (name1 OR name2 OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...).

WorkQuery działa również z jego odpowiednikiem LiveData, getWorkInfosLiveData()

Anulowanie i zatrzymywanie pracy

Jeśli nie potrzebujesz już zadań znajdujących się w kolejce, możesz o to poprosić. ma zostać anulowana. Praca może zostać anulowana przez: name, id lub tag i powiązane z nią.

Kotlin

// by id
workManager.cancelWorkById(syncWorker.id)

// by name
workManager.cancelUniqueWork("sync")

// by tag
workManager.cancelAllWorkByTag("syncTag")

Java

// by id
workManager.cancelWorkById(syncWorker.id);

// by name
workManager.cancelUniqueWork("sync");

// by tag
workManager.cancelAllWorkByTag("syncTag");

W środku WorkManager sprawdza State utworu. Jeśli utwór to już ukończone, nic się nie dzieje. W przeciwnym razie stan utworu zmienia się na CANCELLED i zadanie nie będzie w przyszłości działać. Dowolne WorkRequest zadania, które są zależne w tej pracy również CANCELLED.

Obecnie działa RUNNING odbiera połączenie z numerem ListenableWorker.onStopped() Zastąp tę metodę, aby obsłużyć potencjalne czyszczenie. Zobacz przystanki Run Worker.

Zatrzymaj uruchomioną instancję roboczą

Istnieje kilka różnych powodów, dla których aplikacja Worker może zostać zatrzymana przez WorkManagera:

  • wyraźnie poprosiłeś o anulowanie subskrypcji (za pomocą połączenia telefonicznego, WorkManager.cancelWorkById(UUID)).
  • W przypadku unikalnego utworu jednoznacznie dodano nowy element WorkRequest do kolejki ExistingWorkPolicy z REPLACE. Wcześniejsza subskrypcja WorkRequest zostanie natychmiast uznana za anulowana.
  • Ograniczenia zadania nie są już spełnione.
  • System nakazał aplikacji zatrzymanie pracy z jakiegoś powodu. Może to spowodować może się zdarzyć, jeśli termin wykonania przekroczy 10 minut. Praca jest zaplanowano ponowienie próby w późniejszym czasie.

W tych warunkach instancja robocza zostanie zatrzymana.

Zakończ współpracę i przerwij prac zasoby, z których korzysta pracownik. Na przykład zamknij okno nicki do baz danych i plików. Istnieją 2 mechanizmy na poziomie aby zrozumieć, kiedy pracownik się zatrzymuje.

Wywołanie zwrotne onStopped()

WorkManager wywołuje ListenableWorker.onStopped() w momencie zatrzymania instancji roboczej. Zastąp tę metodę, aby zamknąć wszystkie posiadane przez Ciebie zasoby.

właściwość isStopped(),

Możesz wywołać funkcję ListenableWorker.isStopped(), aby sprawdzić, czy instancja robocza została już zatrzymana. Jeśli wykonując długotrwałe lub powtarzające się operacje w instancji roboczej, często sprawdzaj tę właściwość i używaj jej jako sygnału do natychmiastowego przerwania pracy jak to tylko możliwe.

Uwaga: WorkManager ignoruje wartość Result ustawione przez pracownika które otrzymało sygnał onStop, ponieważ instancja robocza jest już brana pod uwagę zatrzymano.