İş isteklerini tanımlama

Başlangıç kılavuzunda basit bir WorkRequest oluşturma ve sıraya ekleme işlemleri ele alınmıştır.

Bu kılavuzda, yaygın kullanım alanlarını (ör. aşağıdakiler) ele almak için WorkRequest nesnelerini nasıl tanımlayacağınızı ve özelleştireceğinizi öğreneceksiniz:

  • Tek seferlik ve yinelenen işleri planlama
  • Kablosuz ağ veya şarj gerektirme gibi iş kısıtlamaları belirleme
  • İşin yürütülmesinde minimum gecikme garantisi
  • Yeniden deneme ve geri çekilme stratejilerini ayarlama
  • Giriş verilerini işe aktarma
  • Etiketleri kullanarak ilgili çalışmaları bir arada gruplandırma

Genel Bakış

Work, WorkManager'da bir WorkRequest aracılığıyla tanımlanır. WorkManager ile herhangi bir işi planlamak için önce bir WorkRequest nesnesi oluşturmanız ve ardından bu nesneyi sıraya eklemeniz gerekir.

Kotlin

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

Java

WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);

WorkRequest nesnesi, WorkManager'ın işinizi planlamak ve çalıştırmak için ihtiyaç duyduğu tüm bilgileri içerir. İşinizin çalıştırılması için karşılanması gereken kısıtlamaları, gecikmeler veya tekrarlanan aralıklar gibi planlama bilgilerini, yeniden deneme yapılandırmasını içerir ve işiniz bu bilgilere dayanıyorsa giriş verilerini de içerebilir.

WorkRequest, soyut bir temel sınıftır. İsteği oluşturmak için kullanabileceğiniz bu sınıfın iki türetilmiş uygulaması vardır: OneTimeWorkRequest ve PeriodicWorkRequest. Adlarından da anlaşılacağı gibi, OneTimeWorkRequest tekrarlanmayan işleri planlamak için kullanışlıdır. PeriodicWorkRequest ise belirli aralıklarla tekrarlanan işleri planlamak için daha uygundur.

Tek seferlik işleri planlama

Ek yapılandırma gerektirmeyen basit işler için statik yöntemi from kullanın:

Kotlin

val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

Java

WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);

Daha karmaşık işler için bir oluşturucu kullanabilirsiniz:

Kotlin

val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

Java

WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();

Yüksek öncelikli işleri planlama

WorkManager 2.7.0, yüksek öncelikli iş kavramını kullanıma sundu. Bu sayede WorkManager, önemli işleri yürütürken sisteme kaynaklara erişim konusunda daha fazla kontrol sağlar.

Yüksek öncelikli işler aşağıdaki özelliklerle dikkat çeker:

  • Önem: Hızlandırılmış çalışma, kullanıcı için önemli olan veya kullanıcı tarafından başlatılan görevler için uygundur.
  • Hız: Hızlandırılmış çalışma, hemen başlayan ve birkaç dakika içinde tamamlanan kısa görevler için en uygun yöntemdir.
  • Kotalar: Ön planda yürütme süresini sınırlayan sistem düzeyinde bir kota, hızlandırılmış bir işin başlatılıp başlatılamayacağını belirler.
  • Güç Yönetimi: Pil Tasarrufu ve Uyku modu gibi güç yönetimi kısıtlamalarının hızlandırılmış çalışmaları etkileme olasılığı düşüktür.
  • Gecikme: Sistem, mevcut iş yükünün bunu yapmasına izin vermesi koşuluyla hızlandırılmış işleri hemen yürütür. Bu, gecikme duyarlı oldukları ve daha sonra yürütülmek üzere planlanamayacakları anlamına gelir.

Hızlandırılmış çalışmanın potansiyel bir kullanım alanı, kullanıcının bir mesaj veya ek resim göndermek istediği sohbet uygulaması olabilir. Benzer şekilde, ödeme veya abonelik akışını yöneten bir uygulama da hızlandırılmış çalışmayı kullanabilir. Bunun nedeni, bu görevlerin kullanıcı için önemli olması, arka planda hızlı bir şekilde yürütülmesi, hemen başlatılması ve kullanıcı uygulamayı kapatsa bile yürütülmeye devam etmesidir.

Kotalar

Sistem, hızlandırılmış bir işin çalıştırılabilmesi için yürütme süresi ayırmalıdır. Yürütme süresi sınırsız değildir. Bunun yerine, her uygulamaya bir yürütme süresi kotası verilir. Uygulamanız yürütme süresini kullandığında ve ayrılan kotasına ulaştığında, kota yenilenene kadar hızlandırılmış çalışmayı yürütemezsiniz. Bu sayede Android, uygulamaların kaynakları arasında daha etkili bir denge kurabilir.

Bir uygulamanın kullanabileceği yürütme süresi, bekleme paketine ve işleme önemine bağlıdır.

Yürütme kotası, hızlandırılmış bir işin hemen çalışmasına izin vermediğinde ne olacağını belirleyebilirsiniz. Ayrıntılar için aşağıdaki snippet'lere bakın.

Yüksek öncelikli işleri yürütme

WorkManager 2.7'den itibaren uygulamanız, bir WorkRequest'un hızlandırılmış iş kullanarak mümkün olduğunca hızlı çalışacağını beyan etmek için setExpedited()'ü çağırabilir. Aşağıdaki kod snippet'inde setExpedited() işlevinin nasıl kullanılacağıyla ilgili bir örnek verilmiştir:

Kotlin

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

WorkManager.getInstance(context)
    .enqueue(request)

Java

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

Bu örnekte, bir OneTimeWorkRequest örneğini başlatıp üzerinde setExpedited() işlevini çağırıyoruz. Bu talep, hızlandırılmış çalışma olarak kabul edilir. Kota izin veriyorsa hemen arka planda çalışmaya başlar. Kota kullanıldıysa OutOfQuotaPolicy parametresi, isteğin normal şekilde, hızlandırılmamış iş olarak çalıştırılması gerektiğini belirtir.

Geriye dönük uyumluluk ve ön plan hizmetleri

WorkManager, hızlandırılmış işler için geriye dönük uyumluluğu korumak amacıyla Android 12'den eski platform sürümlerinde bir ön plan hizmeti çalıştırabilir. Ön plan hizmetleri kullanıcıya bildirim gösterebilir.

İşleyicinizdeki getForegroundInfoAsync() ve getForegroundInfo() yöntemleri, Android 12'den önce setExpedited() çağrısında bulunduğunuzda WorkManager'ın bildirim göstermesini sağlar.

Görevin hızlandırılmış iş olarak çalışmasını talep etmek istiyorsanız tüm ListenableWorker'ler getForegroundInfo yöntemini uygulamalıdır.

Android 12 veya sonraki sürümleri hedeflediğinizde ön plan hizmetleri, ilgili setForeground yöntemi aracılığıyla kullanılabilir durumda kalır.

Çalışan

Çalışanlar, yaptıkları işin hızlandırılıp hızlandırılmadığını bilmez. Ancak WorkRequest hızlandırıldığında, çalışanlar Android'in bazı sürümlerinde bildirim gösterebilir.

WorkManager, bunu etkinleştirmek için getForegroundInfoAsync() yöntemini sağlar. WorkManager'ın gerektiğinde sizin için bir ForegroundService başlatma bildirimi gösterebilmesi için bu yöntemi uygulamanız gerekir.

CoroutineWorker

CoroutineWorker kullanıyorsanız getForegroundInfo()'ü uygulamanız gerekir. Ardından, doWork() içinde setForeground()'e iletebilirsiniz. Bu işlem, Android 12'den önceki sürümlerde bildirimi oluşturur.

Aşağıdaki örneği inceleyin:

  class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
   CoroutineWorker(appContext, workerParams) {

   override suspend fun getForegroundInfo(): ForegroundInfo {
       return ForegroundInfo(
           NOTIFICATION_ID, createNotification()
       )
   }

   override suspend fun doWork(): Result {
       TODO()
   }

    private fun createNotification() : Notification {
       TODO()
    }

}

Kota politikaları

Uygulamanız yürütme kotasına ulaştığında hızlandırılmış çalışmaya ne olacağını kontrol edebilirsiniz. Devam etmek için setExpedited()'yi iletebilirsiniz:

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST, bu da işin sıradan bir iş isteği olarak çalışmasına neden olur. Yukarıdaki snippet'te bu gösterilmektedir.
  • OutOfQuotaPolicy.DROP_WORK_REQUEST, yeterli kota yoksa isteğin iptal edilmesine neden olur.

Ertelenen yüksek öncelikli iş

Sistem, belirli bir hızlandırılmış işi çağrıldıktan sonra en kısa sürede yürütmeye çalışır. Ancak diğer iş türlerinde olduğu gibi sistem, yeni hızlandırılmış çalışmaların başlangıcını erteleyebilir. Örneğin:

  • Yük: Sistem yükü çok yüksek. Bu durum, çok fazla iş zaten çalışıyorken veya sistemde yeterli bellek olmadığında ortaya çıkabilir.
  • Kota: Hızlandırılmış iş kotası sınırı aşıldı. Hızlandırılmış çalışma, uygulama bekleme gruplarına dayalı bir kota sistemi kullanır ve maksimum yürütme süresini bir zaman aralığında sınırlandırır. Hızlandırılmış çalışma için kullanılan kotalar, diğer arka plan işi türleri için kullanılan kotalardan daha kısıtlayıcıdır.

Periyodik işleri planlama

Uygulamanız bazen belirli işlemlerin düzenli olarak yapılmasını gerektirebilir. Örneğin, verilerinizi düzenli olarak yedeklemek, uygulamanıza yeni içerik indirmek veya günlükleri bir sunucuya yüklemek isteyebilirsiniz.

Düzenli olarak çalışan bir WorkRequest nesnesi oluşturmak için PeriodicWorkRequest'yi aşağıdaki şekilde kullanırsınız:

Kotlin

val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Java

PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

Bu örnekte, çalışma bir saatlik aralıkla planlanmıştır.

Aralık süresi, tekrarlar arasındaki minimum süre olarak tanımlanır. İşleyicinin tam olarak ne zaman çalıştırılacağı, WorkRequest nesnenizde kullandığınız kısıtlamalara ve sistem tarafından yapılan optimizasyonlara bağlıdır.

Esnek çalışma aralıkları

Çalışmanızın doğası nedeniyle çalışma zamanlamasına duyarlıysa PeriodicWorkRequest'ünüzü, Şekil 1'de gösterildiği gibi her aralık döneminde bir esnek dönemde çalışacak şekilde yapılandırabilirsiniz.

Periyodik bir iş için esnek aralık belirleyebilirsiniz. Bir tekrar aralığı ve tekrar aralığının sonunda belirli bir süreyi belirten bir esnek aralık tanımlarsınız. WorkManager, her döngüdeki esnek aralık sırasında işinizi çalıştırmaya çalışır.

Şekil 1. Şemada, işin çalışabileceği esnek dönemle birlikte yinelenen aralıklar gösterilmektedir.

Esnek dönem içeren periyodik çalışmayı tanımlamak için PeriodicWorkRequest oluştururken repeatInterval ile birlikte bir flexInterval iletmeniz gerekir. Esnek dönem repeatInterval - flexInterval'te başlar ve aralığın sonuna kadar devam eder.

Aşağıda, her bir saatlik dönemin son 15 dakikasında çalıştırılabilen düzenli bir çalışma örneği verilmiştir.

Kotlin

val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Java

WorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
               1, TimeUnit.HOURS,
               15, TimeUnit.MINUTES)
           .build();

Tekrar aralığı PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS veya daha büyük, esnek aralığı ise PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS veya daha büyük olmalıdır.

Kısıtlamaların Düzenli Çalışma Üzerindeki Etkisi

Periyodik çalışmaya kısıtlamalar uygulayabilirsiniz. Örneğin, iş isteğinize yalnızca kullanıcının cihazı şarj olurken çalışacak şekilde bir kısıtlama ekleyebilirsiniz. Bu durumda, tanımlanan tekrar aralığı geçse bile PeriodicWorkRequest bu koşul karşılanana kadar çalışmaz. Bu durum, çalışmanızın belirli bir çalıştırmasının gecikmesine veya çalıştırma aralığında koşullar karşılanmadığı takdirde atlanmasına neden olabilir.

Çalışma kısıtlamaları

Kısıtlamalar, çalışmanın en uygun koşullar karşılanana kadar ertelenmesini sağlar. WorkManager aşağıdaki kısıtlamaları kullanabilir.

NetworkType Çalışmanızın çalıştırılması için gereken ağ türünü kısıtlar. Örneğin, kablosuz (UNMETERED).
BatteryNotLow Doğru olarak ayarlandığında, cihaz düşük pil modundaysa çalışmanız çalışmaz.
RequiresCharging Doğru olarak ayarlandığında, çalışmanız yalnızca cihaz şarj olurken çalışır.
DeviceIdle Bu ayar doğru olarak ayarlandığında, çalışmanın çalıştırılması için kullanıcının cihazının boşta olması gerekir. Bu, kullanıcının cihazında etkin olarak çalışan diğer uygulamalar üzerinde olumsuz bir performans etkisi olabilecek toplu işlemleri çalıştırmak için yararlı olabilir.
StorageNotLow Doğru değerine ayarlanırsa kullanıcının cihazdaki depolama alanı çok düşükse çalışmanız çalışmaz.

Bir dizi kısıtlama oluşturmak ve bu kısıtlamaları bir çalışmayla ilişkilendirmek için Contraints.Builder() kullanarak bir Constraints örneği oluşturun ve bu örneği WorkRequest.Builder()'inize atayın.

Örneğin, aşağıdaki kod yalnızca kullanıcının cihazı hem şarj oluyor hem de kablosuz ağa bağlıyken çalışan bir iş isteği oluşturur:

Kotlin

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

Java

Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setConstraints(constraints)
               .build();

Birden fazla kısıtlama belirtildiğinde çalışmanız yalnızca tüm kısıtlamalar karşılandığında çalışır.

İşiniz çalışırken bir kısıtlamanın karşılanmaması durumunda WorkManager, işleyicinizi durdurur. Tüm kısıtlamalar karşılandığında çalışma yeniden denenir.

Gecikmeli Çalışma

Çalışmanızda herhangi bir kısıtlama yoksa veya çalışmanız sıraya eklendiğinde tüm kısıtlamalar karşılanıyorsa sistem, çalışmayı hemen çalıştırmayı seçebilir. Çalışmanın hemen çalıştırılmasını istemiyorsanız minimum bir başlangıç gecikmesinden sonra çalışmanızın başlatılacağını belirtebilirsiniz.

Çalışmanızın, sıraya eklendikten en az 10 dakika sonra çalışacak şekilde nasıl ayarlanacağına dair bir örnek aşağıda verilmiştir.

Kotlin

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

Java

WorkRequest myWorkRequest =
      new OneTimeWorkRequest.Builder(MyWork.class)
               .setInitialDelay(10, TimeUnit.MINUTES)
               .build();

Örnekte, bir OneTimeWorkRequest için ilk gecikmenin nasıl ayarlanacağı gösterilmektedir. PeriodicWorkRequest için de ilk gecikme ayarlayabilirsiniz. Bu durumda, yalnızca düzenli işinizin ilk çalıştırması gecikecektir.

Yeniden deneme ve geri çekilme politikası

WorkManager'ın çalışmanızı yeniden denemesini istiyorsanız işleyicinizden Result.retry() döndürebilirsiniz. Ardından, çalışmanız geri çekilme gecikmesine ve geri çekilme politikasına göre yeniden planlanır.

  • Geri yükleme gecikmesi, ilk denemeden sonra çalışmanızı yeniden denemeden önce beklemeniz gereken minimum süreyi belirtir. Bu değer en az 10 saniye (veya MIN_BACKOFF_MILLIS) olmalıdır.

  • Geri çekilme politikası, sonraki yeniden deneme girişimleri için geri çekilme gecikmesinin zaman içinde nasıl artması gerektiğini tanımlar. WorkManager, LINEAR ve EXPONENTIAL olmak üzere 2 geri çekilme politikasını destekler.

Her çalışma isteği için bir geri çekilme politikası ve geri çekilme gecikmesi vardır. Varsayılan politika, 30 saniyelik gecikmeyle EXPONENTIAL'tür ancak bunu iş isteği yapılandırmanızda geçersiz kılabilirsiniz.

Aşağıda, geri çekilme gecikmesi ve politikasının özelleştirilmesine ilişkin bir örnek verilmiştir.

Kotlin

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

Java

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();

Bu örnekte, minimum geri yükleme gecikmesi izin verilen minimum değere (10 saniye) ayarlanmıştır. Politika LINEAR olduğundan, her yeni denemeyle birlikte yeniden deneme aralığı yaklaşık 10 saniye artar. Örneğin, Result.retry() ile biten ilk çalıştırma 10 saniye sonra tekrar denenir. Çalışma, sonraki denemelerden sonra Result.retry() döndürmeye devam ederse 20, 30, 40 saniye vb. sonra tekrar denenir. Geri çekilme politikası EXPONENTIAL olarak ayarlanmışsa yeniden deneme süresi sırası 20, 40, 80 vb. şeklinde olur.

Çalışmayı etiketleme

Her iş isteği, iptal etmek veya ilerlemesini gözlemlemek için daha sonra bu işi tanımlamak üzere kullanılabilecek bir benzersiz tanımlayıcıya sahiptir.

Mantıksal olarak birbiriyle ilişkili bir iş grubunuz varsa bu iş öğelerini etiketlemeyi de faydalı bulabilirsiniz. Etiketleme, bir grup iş isteğiyle birlikte çalışmanıza olanak tanır.

Örneğin, WorkManager.cancelAllWorkByTag(String) belirli bir etikete sahip tüm iş isteklerini iptal eder ve WorkManager.getWorkInfosByTag(String), mevcut iş durumunu belirlemek için kullanılabilecek WorkInfo nesnelerinin listesini döndürür.

Aşağıdaki kod, çalışmanıza nasıl "temizlik" etiketi ekleyeceğinizi gösterir:

Kotlin

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Java

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("cleanup")
       .build();

Son olarak, tek bir iş isteğine birden fazla etiket eklenebilir. Bu etiketler dahili olarak bir dize dizisi olarak depolanır. WorkRequest ile ilişkili etiket grubunu almak için WorkInfo.getTags() işlevini kullanabilirsiniz.

Worker sınıfınızdaki etiket grubunu ListenableWorker.getTags() aracılığıyla alabilirsiniz.

Giriş verilerini atama

Çalışmanızın çalışması için giriş verileri gerekebilir. Örneğin, bir resmin yüklenmesini yöneten çalışma, yüklenecek resmin URI'sinin giriş olarak kullanılmasını gerektirebilir.

Giriş değerleri, Data nesnesinde anahtar/değer çiftleri olarak depolanır ve çalışma isteğinde ayarlanabilir. WorkManager, işi yürüttüğünde Data girişini işinize gönderir. Worker sınıfı, Worker.getInputData()'u çağırarak giriş bağımsız değişkenlerine erişebilir. Aşağıdaki kodda, giriş verisi gerektiren bir Worker örneğinin nasıl oluşturulacağı ve bu örneğin iş isteğinizde nasıl gönderileceği gösterilmektedir.

Kotlin

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Java

// Define the Worker requiring input
public class UploadWork extends Worker {

   public UploadWork(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String imageUriInput = getInputData().getString("IMAGE_URI");
       if(imageUriInput == null) {
           return Result.failure();
       }

       uploadFile(imageUriInput);
       return Result.success();
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("IMAGE_URI", "http://...")
                   .build()
           )
           .build();

Benzer şekilde, döndürülen bir değer çıkışı için Data sınıfı kullanılabilir. Giriş ve çıkış verileri, giriş parametreleri ve döndürülen değerler bölümünde daha ayrıntılı olarak ele alınmıştır.

Sonraki Adımlar

Durumlar ve gözlem sayfasında, çalışma durumları ve çalışmanızın ilerleme durumunu nasıl izleyeceğiniz hakkında daha fazla bilgi edinebilirsiniz.