İşleri yönetme

Worker ve WorkRequest tanımladıktan sonraki son adım, çalışmanızı sıraya almak olacaktır. İşleri sıraya almanın en basit yolu, çalıştırmak istediğiniz WorkRequest öğesini ileterek WorkManager enqueue() yöntemini çağırmaktır.

Kotlin

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

Java

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

Çalışmaları sıraya alırken yinelemeyi önlemek için dikkatli olun. Örneğin, bir uygulama günlüklerini 24 saatte bir arka uç hizmetine yüklemeye çalışabilir. Dikkatli olmazsanız işin yalnızca bir kez çalışması gerekmesine rağmen aynı görevi birçok kez sıraya alabilirsiniz. Bu hedefe ulaşmak için işi benzersiz iş olarak planlayabilirsiniz.

Benzersiz Çalışma

Benzersiz çalışma, belirli bir ada sahip çalışmanın aynı anda yalnızca bir örneğinin olmasını sağlayan güçlü bir kavramdır. Kimliklerin aksine, benzersiz adlar insanlar tarafından okunabilir ve WorkManager tarafından otomatik olarak oluşturulmak yerine geliştirici tarafından belirtilir. Benzersiz adlar, etiketlerin aksine yalnızca tek bir çalışma örneğiyle ilişkilendirilir.

Benzersiz çalışma, hem tek seferlik hem de düzenli çalışmalara uygulanabilir. Tekrarlanan bir iş veya tek seferlik bir iş planlamanıza bağlı olarak bu yöntemlerden birini çağırarak benzersiz bir iş sırası oluşturabilirsiniz.

Bu yöntemlerin her ikisi de 3 bağımsız değişken kabul eder:

  • uniqueWorkName: Çalışma isteğini benzersiz şekilde tanımlamak için kullanılan String.
  • existingWorkPolicy - Bu benzersiz ada sahip, tamamlanmamış bir iş zinciri zaten varsa WorkManager'a ne yapması gerektiğini söyleyen bir enum. Daha fazla bilgi için çakışma çözümü politikasına bakın.
  • work: Planlanacak WorkRequest.

Benzersiz bir çalışma kullanarak daha önce belirtilen yinelenen planlama sorunumuzu düzeltebiliriz.

Kotlin

val sendLogsWorkRequest =
       PeriodicWorkRequestBuilder<SendLogsWorker>(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);

Artık kod, sendLogs işi zaten kuyruktayken çalıştırılırsa mevcut iş korunur ve yeni iş eklenmez.

Uzun bir görev zinciri oluşturmanız gerektiğinde benzersiz iş sıraları da faydalı olabilir. Örneğin, bir fotoğraf düzenleme uygulaması, kullanıcıların uzun bir işlem zincirini geri almasına izin verebilir. Bu geri alma işlemlerinin her biri biraz zaman alabilir ancak doğru sırayla gerçekleştirilmesi gerekir. Bu durumda uygulama, bir "geri alma" zinciri oluşturabilir ve her geri alma işlemini gerektiğinde zincire ekleyebilir. Daha fazla bilgi için Çalışmaları zincirleme bölümüne bakın.

Çatışma çözümü politikası

Benzersiz bir iş planlarken WorkManager'a çakışma olduğunda hangi işlemi yapması gerektiğini söylemeniz gerekir. Bunu, işi sıraya alırken bir enum ileterek yaparsınız.

Tek seferlik işler için, çakışmanın ele alınmasıyla ilgili 4 seçeneği destekleyen bir ExistingWorkPolicy sağlarsınız.

  • REPLACE mevcut çalışmayı yeni çalışmayla karşılaştırın. Bu seçenek, mevcut çalışmayı iptal eder.
  • KEEP mevcut çalışmayı ve yeni çalışmayı yoksay.
  • APPEND yeni çalışmayı mevcut çalışmanın sonuna. Bu politika, yeni çalışmanızın mevcut çalışmaya bağlanmasına ve mevcut çalışma tamamlandıktan sonra çalışmasına neden olur.

Mevcut çalışma, yeni çalışmanın ön koşulu haline gelir. Mevcut çalışma CANCELLED veya FAILED olursa yeni çalışma da CANCELLED veya FAILED olur. Yeni işin mevcut işin durumundan bağımsız olarak çalışmasını istiyorsanız bunun yerine APPEND_OR_REPLACE kullanın.

  • APPEND_OR_REPLACE, APPEND ile benzer şekilde çalışır ancak ön koşul iş durumuyla ilişkili değildir. Mevcut çalışma CANCELLED veya FAILED ise yeni çalışma yine de çalışır.

Dönem çalışması için REPLACE ve KEEP olmak üzere 2 seçeneği destekleyen bir ExistingPeriodicWorkPolicy sağlarsınız. Bu seçenekler, ExistingWorkPolicy karşılıklarıyla aynı şekilde çalışır.

Çalışmanızı gözlemleme

İş kuyruğa alındıktan sonra istediğiniz zaman name, id veya tag ile WorkManager'ı sorgulayarak işin durumunu kontrol edebilirsiniz.

Kotlin

// by id
workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo>

// by name
workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>>

// by tag
workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>>

Java

// by id
workManager.getWorkInfoById(syncWorker.id); // ListenableFuture<WorkInfo>

// by name
workManager.getWorkInfosForUniqueWork("sync"); // ListenableFuture<List<WorkInfo>>

// by tag
workManager.getWorkInfosByTag("syncTag"); // ListenableFuture<List<WorkInfo>>

Sorgu, ListenableFuture WorkInfo nesnesini döndürür. Bu nesne, çalışmanın id, etiketleri, mevcut State ve Result.success(outputData) kullanan tüm çıkış veri kümelerini içerir.

Her yöntemin LiveData ve Flow varyantları, bir dinleyici kaydederek WorkInfo değişikliklerini gözlemlemenizi sağlar. Örneğin, bir işlem başarıyla tamamlandığında kullanıcıya mesaj göstermek istiyorsanız bunu aşağıdaki gibi ayarlayabilirsiniz:

Kotlin

workManager.getWorkInfoByIdFlow(syncWorker.id)
          .collect{ 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();
   }
});

Karmaşık iş sorguları

WorkManager 2.4.0 ve sonraki sürümler, WorkQuery nesneleri kullanılarak sıraya alınmış işler için karmaşık sorgulamayı destekler. WorkQuery, sorgulama için işleri etiketleri, durumu ve benzersiz iş adının bir kombinasyonuyla destekler.

Aşağıdaki örnekte, FAILED veya CANCELLED durumunda olan ve"preProcess" ya da "sync" şeklinde benzersiz bir çalışma adına sahip olan, "syncTag" etiketli tüm çalışmaları nasıl bulabileceğiniz gösterilmektedir.

Kotlin

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

val workInfos: ListenableFuture<List<WorkInfo>> = 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();

ListenableFuture<List<WorkInfo>> workInfos = workManager.getWorkInfos(workQuery);

Bir WorkQuery içindeki her bileşen (etiket, durum veya ad), diğerleriyle AND. Bir bileşendeki her değer OR ile ayrılır. Örneğin: (name1 OR name2 OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...).

WorkQuery, LiveData eşdeğeri olan getWorkInfosLiveData() ve Flow eşdeğeri olan getWorkInfosFlow() ile de çalışır.

Çalışmayı iptal etme ve durdurma

Daha önce sıraya aldığınız işin artık çalıştırılmasına gerek yoksa iptal edilmesini isteyebilirsiniz. Çalışma, name, id veya tag tarafından iptal edilebilir.

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

WorkManager, arka planda çalışmanın State olup olmadığını kontrol eder. Çalışma tamamlanmışsa herhangi bir değişiklik olmaz. Aksi takdirde, işin durumu CANCELLED olarak değiştirilir ve iş gelecekte çalışmaz. WorkRequest işleri bu çalışmaya bağımlıysa onlar da CANCELLED olur.

RUNNING çalışanı ListenableWorker.onStopped() numaralı telefondan arama alıyor. Olası temizleme işlemlerini gerçekleştirmek için bu yöntemi geçersiz kılın. Daha fazla bilgi için çalışan bir işi durdurma başlıklı makaleyi inceleyin.

Çalışan bir Worker'ı durdurma

Çalışan Worker'nızın WorkManager tarafından durdurulmasının birkaç farklı nedeni olabilir:

  • İptal edilmesini açıkça istemişsinizdir (örneğin, WorkManager.cancelWorkById(UUID) numaralı telefonu arayarak).
  • Benzersiz çalışma durumunda, REPLACE ExistingWorkPolicy ile yeni bir WorkRequest açıkça sıraya alınır. Eski WorkRequest hemen iptal edilmiş olarak kabul edilir.
  • Çalışmanızın kısıtlamaları artık karşılanmıyor.
  • Sistem, uygulamanıza çalışmayı durdurmasını söyledi. Bu durum, 10 dakikalık yürütme son tarihini aşarsanız meydana gelebilir. İşin daha sonra yeniden denenmesi planlanıyor.

Bu koşullar altında Worker'ınız durdurulur.

Devam eden tüm çalışmaları işbirliği içinde durdurmalı ve Worker'ınızın tuttuğu tüm kaynakları serbest bırakmalısınız. Örneğin, bu noktada veritabanları ve dosyalarla ilgili açık tutamaçları kapatmanız gerekir. Çalışanınızın ne zaman durduğunu anlamak için kullanabileceğiniz iki mekanizma vardır.

onStopped() geri çağırması

WorkManager, Worker'ınız durdurulur durdurulmaz ListenableWorker.onStopped()'ı çağırır. Elde tuttuğunuz kaynakları kapatmak için bu yöntemi geçersiz kılın.

isStopped() özelliği

Çalışanınızın durdurulup durdurulmadığını kontrol etmek için ListenableWorker.isStopped() yöntemini çağırabilirsiniz. Worker'ınızda uzun süren veya tekrarlanan işlemler gerçekleştiriyorsanız bu özelliği sık sık kontrol etmeli ve mümkün olan en kısa sürede çalışmayı durdurmak için bir sinyal olarak kullanmalısınız.

Not: WorkManager, onStop sinyalini almış bir Worker tarafından ayarlanan Result değerini yoksayar. Bunun nedeni, Worker'ın zaten durdurulmuş olarak kabul edilmesidir.