İşleri yönetme

Worker ve WorkRequest tanımlarınızı belirledikten sonra son adım, çalışmanızı sıraya koymaktır. İşleri sıraya eklemenin 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);

Yinelemeleri önlemek için çalışmaları sıraya eklerken dikkatli olun. Örneğin, bir uygulama 24 saatte bir günlüklerini bir arka uç hizmetine yüklemeyi deneyebilir. Dikkatli olmazsanız işin yalnızca bir kez çalıştırılması gerekse bile aynı görevi birçok kez kuyruğa alabilirsiniz. Bu hedefe ulaşmak için çalışmayı benzersiz çalışma olarak programlayabilirsiniz.

Benzersiz Çalışma

Benzersiz iş, belirli bir ad ile aynı anda yalnızca bir çalışma örneğinizin olduğunu garanti eden güçlü bir kavramdır. Kimliklerin aksine, benzersiz adlar kullanıcılar tarafından okunabilir ve WorkManager tarafından otomatik olarak oluşturulmak yerine geliştirici tarafından belirtilir. Etiketlerin aksine, benzersiz adlar yalnızca tek bir çalışma örneğiyle ilişkilendirilir.

Benzersiz çalışma, hem tek seferlik hem de dönemsel çalışmalara uygulanabilir. Tekrarlanan bir iş mi yoksa tek seferlik bir çalışma mı planladığınıza bağlı olarak bu yöntemlerden birini çağırarak benzersiz bir iş dizisi oluşturabilirsiniz.

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

  • uniqueWorkName - İş isteğini benzersiz şekilde tanımlamak için kullanılan String.
  • existingWorkPolicy - Bu benzersiz ada sahip olan tamamlanmamış bir iş zinciri varsa WorkManager'a ne yapacağını bildiren bir enum. Daha fazla bilgi için çakışma çözümü politikasını inceleyin.
  • work - planlanacak WorkRequest.

Benzersiz çalışma kullanarak daha önce belirttiğimiz yinelenen planlama sorunumuzu çözebiliriz.

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 bir sendLogs işi sıradayken kod çalışırsa mevcut iş korunur ve yeni iş eklenmez.

Benzersiz iş adım sıraları, aşamalı olarak uzun bir görev zinciri oluşturmanız gerektiğinde de yararlı olabilir. Örneğin, bir fotoğraf düzenleme uygulaması, kullanıcıların uzun bir işlem zincirini geri almalarına olanak tanıyabilir. Bu geri alma işlemlerinin her biri biraz zaman alabilir, ancak işlemlerin doğru sırayla gerçekleştirilmesi gerekir. Bu durumda, uygulama bir "geri al" zinciri oluşturabilir ve her geri alma işlemini gerektiği şekilde zincire ekleyebilir. Daha fazla bilgi için Zincirleme iş bölümünü inceleyin.

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

Benzersiz çalışma planlarken, WorkManager'a bir çakışma olduğunda hangi işlemi gerçekleştireceğini bildirmeniz gerekir. Bunu işi sıraya alırken bir enum ileterek yaparsınız.

Tek seferlik çalışma için çakışmayı yönetmek için 4 seçeneği destekleyen bir ExistingWorkPolicy sağlarsınız.

  • REPLACE mevcut çalışmayı değiştirebilir. Bu seçenek mevcut çalışmayı iptal eder.
  • KEEP mevcut çalışmayı ve yeni çalışmayı yoksayabilirsiniz.
  • APPEND yeni çalışmayı mevcut çalışmanın sonuna aktarın. Bu politika, yeni çalışmanızın mevcut iş bittikten sonra çalıştırılacak şekilde mevcut çalışmaya zincirlenmesine neden olur.

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

  • APPEND_OR_REPLACE, APPEND işlevine benzer şekilde çalışır. Tek fark, ön koşul çalışma durumuna bağlı olmamasıdır. Mevcut çalışma CANCELLED veya FAILED ise yeni çalışma çalışmaya devam eder.

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, MevcutWorkPolicy'ler ile aynı şekilde çalışır.

Çalışmanızı gözlemleme

Çalışmayı sıraya aldıktan sonra herhangi bir noktada, WorkManager'ı name, id veya onunla ilişkilendirilmiş tag kodu ile sorgulayarak 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, bir WorkInfo nesnesinin ListenableFuture bilgisini döndürür. İşin id öğesi, etiketleri, mevcut State ve Result.success(outputData) aracılığıyla ayarlanan tüm çıkış verileri bu kapsamdadır.

Yöntemlerin her birinin LiveData varyantı, bir işleyici kaydederek WorkInfo öğesinde yapılan değişiklikleri gözlemlemenize olanak tanır. Örneğin, bazı işler başarıyla tamamlandığında kullanıcıya bir mesaj görüntülemek istiyorsanız bunu şu şekilde ayarlayabilirsiniz:

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();
   }
});

Karmaşık iş sorguları

WorkManager 2.4.0 ve sonraki sürümler, WorkQuery nesnelerini kullanarak sıraya alınmış işler için karmaşık sorgulamaları destekler. WorkQuery, etiketleri, durumu ve benzersiz iş adı kombinasyonuna göre iş sorgulamayı destekler.

Aşağıdaki örnekte, FAILED veya CANCELLED durumundaki ve benzersiz bir iş adı olan "preProcess" ya da "sync" olan "syncTag" etiketiyle 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);

WorkQuery içindeki her bileşen (etiket, durum veya ad) diğerleriyle AND-edilir. Bir bileşendeki her değer OR-ed'dir. Örneğin: (name1 OR name2 OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...).

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

İşleri iptal etme ve durdurma

Daha önce sıraya aldığınız çalışmanın artık yayınlanması için ihtiyacınız yoksa iptal edilmesini isteyebilirsiniz. İş, name, id veya onunla ilişkili bir 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 işin State durumunu kontrol eder. İş bittiyse hiçbir şey olmaz. Aksi takdirde, çalışmanın durumu CANCELLED olarak değiştirilir ve çalışma gelecekte çalışmaz. Bu işe bağlı olan tüm WorkRequest işleri de CANCELLED olacaktır.

Şu anda RUNNING kullanıcıya ListenableWorker.onStopped() çağrısı yapılıyor. Olası temizleme işlemlerini işlemek için bu yöntemi geçersiz kılın. Daha fazla bilgi için çalışan bir çalışanı durdurma bölümüne bakın.

Çalışan bir Çalışanı durdurun

Worker adlı çalıştırmanızın WorkManager tarafından durdurulmasının birkaç farklı nedeni olabilir:

  • Açıkça iptal edilmesini istediniz (örneğin, WorkManager.cancelWorkById(UUID) numaralı telefonu arayarak).
  • Benzersiz çalışma söz konusu olduğunda, yeni bir WorkRequest öğesini açıkça REPLACE değeri ExistingWorkPolicy ile sıraya eklediniz. Eski WorkRequest hemen iptal edilmiş olarak kabul edilir.
  • İşinizin kısıtlamaları artık karşılanmıyor.
  • Sistem, uygulamanıza bir nedenle çalışmanızı durdurma talimatı verdi. Bu durum, son 10 dakikalık yürütme süresini aşarsanız gerçekleşebilir. Çalışmanın daha sonra yeniden denenmesi planlanır.

Bu koşullarda Çalışanınız durdurulur.

Devam etmekte olan tüm çalışmaları iş birliği içinde iptal etmeli ve Çalışanınızın elindeki kaynakları serbest bırakmalısınız. Örneğin, bu noktada veritabanlarına ve dosyalara 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, Çalışan durdurulduğunda ListenableWorker.onStopped() komutunu çağırır. Beklediğiniz 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. Çalışanınızda uzun süreli veya tekrarlanan işlemler gerçekleştiriyorsanız bu özelliği sık sık kontrol etmeli ve işi mümkün olan en kısa sürede durdurmak için sinyal olarak kullanmalısınız.

Not: WorkManager, onStop sinyalini alan bir Çalışan tarafından ayarlanan Result özelliğini yok sayar. Bunun nedeni, Çalışanın zaten durdurulmuş kabul edilmesidir.