İş 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, aşağıdaki gibi yaygın kullanım alanlarını ele almak için WorkRequest nesnelerini tanımlamayı ve özelleştirmeyi öğreneceksiniz:

  • Tek seferlik ve yinelenen işler programlama
  • 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. Bu sınıfın, isteği oluşturmak için kullanabileceğiniz 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 Doz gibi güç yönetimi kısıtlamalarının hızlandırılmış işi etkileme olasılığı daha düşüktür.
  • Gecikme: Sistem, mevcut iş yükünün bunu yapmasına izin vermesi koşuluyla hızlandırılmış işi 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ı yürütülmesi, hemen başlatılması ve kullanıcı uygulamayı kapatsa bile yürütülmeye devam etmesinin gerekmesidir.

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, kaynakları uygulamalar arasında daha etkili bir şekilde dengeleyebilir.

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 ve hızlandırılmamış çalışma olarak çalıştırılması gerektiğini gösterir.

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

Hızlandırılmış işlerin geriye dönük uyumluluğu sağlamak amacıyla WorkManager, 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ı bilmiyor. Ancak bir WorkRequest hızlandırıldığında çalışanlar Android'in bazı sürümlerinde bildirim görüntüleyebilir.

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.

Eş yordam

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() ayarını geçirebilirsiniz:

  • 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.

Örnek uygulama

WorkManager 2.7.0'ın hızlandırılmış işi nasıl kullandığına dair tam bir örnek görmek için GitHub'daki WorkManagerSample'e göz atın.

Ertelenen, hızlandırılmış çalışma

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 yürütülen bir WorkRequest nesnesi oluşturmak için PeriodicWorkRequest öğesini şu şekilde kullanabilirsiniz:

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 ayarlayabilirsiniz. Bir tekrarlama aralığı ve tekrarlama 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, çalışmanın yalnızca kullanıcının cihazı şarj olurken çalışacağı ş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şılanmıyorsa 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. Aşağıdaki kısıtlamalar WorkManager tarafından kullanılabilir.

Ağ Türü Çalışmanızın çalışması için gereken ağ türünü kısıtlar. Örneğin, kablosuz (UNMETERED).
BatteryNotLow Doğru değerine ayarlandığında, cihaz düşük pil modunda olduğunda çalışmanız çalışmaz.
Şarj Gerekiyor Doğru değerine ayarlanırsa çalışmanız yalnızca cihaz şarj olurken çalışır.
DeviceIdle Politika, Doğru değerine ayarlandığında çalışmanın çalışması 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 Politika, Doğru değerine ayarlandığında kullanıcının cihazdaki depolama alanı çok azsa ç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 olurken hem de kablosuz ağa bağlıyken çalıştırılan 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 gerçekleştirilir.

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

Gecikmeli Çalışma

Çalışmanızda herhangi bir kısıtlama olmaması veya çalışmanız sıraya alındığında tüm kısıtlamaların karşılanması halinde sistem, çalışmayı hemen çalıştırmayı seçebilir. Çalışmanın hemen çalıştırılmasını istemiyorsanız çalışmanızın minimum bir başlangıç gecikmesinin ardından başlaması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 alma politikası

WorkManager'ın çalışmanızı yeniden denemesini istiyorsanız işleyicinizden Result.retry() döndürebilirsiniz. Daha sonra çalışmanız bir geri yükleme gecikmesi ve geri alma 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 yükleme politikasını destekler.

Her çalışma isteğinin 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 yükleme gecikmesini ve politikasını özelleştirmeyle ilgili 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ğinin benzersiz bir tanımlayıcısı vardır. Bu tanımlayıcı, daha sonra çalışmayı iptal etmek veya ilerleme durumunu gözlemlemek için kullanılabilir.

Mantıksal olarak birbiriyle ilişkili bir iş grubunuz varsa bu iş öğelerini etiketlemeyi de yararlı 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 çalışma durumunu belirlemek için kullanılabilecek WorkInfo nesnelerinin bir listesini döndürür.

Aşağıdaki kod, işinize bir "temizlik" etiketini nasıl ekleyebileceğ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özlemler sayfasında çalışma durumları ve çalışmanızın ilerlemesini nasıl izleyeceğiniz hakkında daha fazla bilgi edinebilirsiniz.