İş isteklerini tanımlama

Başlangıç kılavuzunda, WorkRequest oluşturma ve sıraya alma işlemi açıklanmıştır.

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

  • Tek seferlik ve yinelenen işleri planlama
  • Kablosuz bağlantı veya şarj gerektirme gibi çalışma kısıtlamaları ayarlama
  • İş yürütmesinde minimum gecikme garantisi
  • Yeniden deneme ve geri çekilme stratejilerini ayarlama
  • Giriş verilerini işleme
  • İlgili çalışmaları etiketleri kullanarak gruplandırma

Genel Bakış

WorkManager'da iş, WorkRequest kullanılarak tanımlanır. WorkManager ile herhangi bir işi planlamak için önce bir WorkRequest nesnesi oluşturup ardından bunu 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. Çalışmanızın çalışması 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 çalışmanız buna bağlıysa giriş verilerini içerebilir.

WorkRequest kendisi 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, PeriodicWorkRequest ise belirli aralıklarla tekrarlanan işleri planlamak için daha uygundur.

Tek seferlik işleri planlama

Ek yapılandırma gerektirmeyen temel işlemler 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 çalışmalar 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 görevleri yürütürken sisteme kaynaklara erişim üzerinde daha iyi kontrol imkanı tanır.

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

  • Önem: Yüksek öncelikli iş, 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 seçenektir.
  • Kotalar: Ön planda yürütme süresini sınırlayan sistem düzeyinde bir kota, yüksek öncelikli 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 yüksek öncelikli işi etkileme olasılığı daha düşüktür.
  • Gecikme: Sistem, mevcut iş yükünün buna izin vermesi koşuluyla yüksek öncelikli işi hemen yürütür. Bu, işin gecikmeye duyarlı olduğu ve daha sonra yürütülecek şekilde planlanamayacağı anlamına gelir.

Yüksek öncelikli iş için olası bir kullanım alanı, kullanıcının mesaj veya ekli resim göndermek istediği bir sohbet uygulaması olabilir. Benzer şekilde, ödeme veya abonelik akışını yöneten bir uygulama da yüksek öncelikli iş kullanmak isteyebilir. 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 etmesi gerektiğidir.

Kotalar

Sistemin, yüksek öncelikli bir işin çalışabilmesi için önce yürütme süresi ayırması gerekir. Yürütme süresi sınırsız değildir. Bunun yerine, her uygulama için bir yürütme süresi kotası belirlenir. Uygulamanız yürütme süresini kullandığında ve ayrılan kotasına ulaştığında, kota yenilenene kadar artık yüksek öncelikli iş yürütemezsiniz. Bu sayede Android, uygulamalar arasındaki kaynakları daha etkili bir şekilde dengeleyebilir.

Bir uygulamaya sunulan yürütme süresi miktarı, bekleme paketi ve süreç önemine göre belirlenir.

Yürütme kotası, yüksek öncelikli bir işin hemen çalıştırılması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, setExpedited() işinin yüksek öncelikli bir iş kullanılarak mümkün olduğunca hızlı çalışması gerektiğini bildirmek için WorkRequest işlevini çağırabilir. Aşağıdaki kod snippet'inde setExpedited() öğesinin nasıl kullanılacağına dair bir örnek verilmiştir:

Kotlin

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

WorkManager.getInstance(context)
    .enqueue(request)

Java

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

Bu örnekte, OneTimeWorkRequest sınıfının bir örneğini başlatıp üzerinde setExpedited() yöntemini çağırıyoruz. Bu istek daha sonra yüksek öncelikli iş haline gelir. Kota izin veriyorsa hemen arka planda çalışmaya başlar. Kota kullanıldıysa OutOfQuotaPolicy parametresi, isteğin normal, hızlandırılmamış bir işlem olarak çalıştırılması gerektiğini belirtir.

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

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

Worker'ınızdaki getForegroundInfoAsync() ve getForegroundInfo() yöntemleri, Android 12'den önceki sürümlerde setExpedited()'ı çağırdığınızda WorkManager'ın bildirim göstermesini sağlar.

Görevlerin yüksek öncelikli bir iş olarak çalıştırılmasını istiyorsanız tüm ListenableWorker, getForegroundInfo yöntemini uygulamalıdır.

Android 12 veya sonraki sürümler hedeflenirken ön plan hizmetleri, ilgili setForeground yöntemiyle kullanılabilir.

Çalışan

Çalışanlar, yaptıkları işin hızlandırılmış olup olmadığını bilmiyor. Ancak çalışanlar, WorkRequest hızlandırıldığında Android'in bazı sürümlerinde bildirim gösterebilir.

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

CoroutineWorker

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

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

  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 yüksek öncelikli işlerin ne olacağını kontrol edebilirsiniz. Devam etmek için setExpedited() sınavını geçebilirsiniz:

  • OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST, bu da işin normal bir iş isteği olarak çalışmasına neden olur. Önceki snippet bunu gösteriyor.
  • OutOfQuotaPolicy.DROP_WORK_REQUEST. Bu değer, yeterli kota yoksa isteğin iptal edilmesine neden olur.

Ertelenen yüksek öncelikli iş

Sistem, belirli bir yüksek öncelikli işi çağrıldıktan sonra mümkün olan en kısa sürede yürütmeye çalışır. Ancak diğer iş türlerinde olduğu gibi, sistem aşağıdaki gibi durumlarda yeni yüksek öncelikli işlerin başlangıcını erteleyebilir:

  • Yük: Sistem yükü çok yüksek. Bu durum, çok fazla iş zaten çalışırken veya sistemde yeterli bellek olmadığında ortaya çıkabilir.
  • Kota: Yüksek öncelikli iş kotası sınırı aşıldı. Yüksek öncelikli iş, Uygulamayı Beklemeye Alma Gruplarına dayalı bir kota sistemi kullanır ve kayan bir zaman aralığındaki maksimum yürütme süresini sınırlar. Yüksek öncelikli iş 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 çalışma planlama

Uygulamanızın zaman zaman belirli işlemlerin düzenli olarak çalışmasını gerektirmesi mümkündür. Örneğin, verilerinizi düzenli olarak yedeklemek, uygulamanıza yeni içerikler indirmek veya günlükleri bir sunucuya yüklemek isteyebilirsiniz.

Periyodik olarak yürütülen bir PeriodicWorkRequest oluşturmak için WorkRequest nesnesini ş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 saat aralıklarla planlanmıştır.

Aralık süresi, tekrarlar arasındaki minimum süre olarak tanımlanır. Çalışanın tam olarak ne zaman yürütüleceği, WorkRequest nesnenizde kullandığınız kısıtlamalara ve sistem tarafından gerçekleştirilen optimizasyonlara bağlıdır.

Esnek koşu aralıkları

İşinizin doğası, zamanlamaya duyarlı olmanızı gerektiriyorsa Şekil 1'de gösterildiği gibi PeriodicWorkRequest'nizi her aralık döneminde esnek bir dönem içinde çalışacak şekilde yapılandırabilirsiniz.

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

Şekil 1. Şemada, çalışmanın yürütülebileceği esnek dönemle birlikte yinelenen aralıklar gösterilmektedir.

Esnek dönem içeren periyodik çalışma tanımlamak için flexInterval oluştururken PeriodicWorkRequest ile birlikte repeatInterval değerini iletirsiniz. Esneklik dönemi repeatInterval - flexInterval tarihinde başlar ve aralığın sonuna kadar devam eder.

Aşağıda, her saatlik dönemin son 15 dakikasında çalıştırılabilen periyodik bir iş ö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 değerine eşit veya bu değerden büyük olmalı, esnek aralık ise PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS` değerine eşit veya bu değerden büyük olmalıdır.

Kısıtlamaların Periyodik Çalışma Üzerindeki Etkisi

Periyodik çalışmalara 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 bu koşul karşılanana kadar PeriodicWorkRequest çalıştırılmaz. Bu durum, işinizin belirli bir çalıştırmasının gecikmesine veya koşullar çalıştırma aralığında karşılanmazsa atlanmasına neden olabilir.

Çalışma kısıtlamaları

Constraints Çalışmanın, en uygun koşullar sağlanana kadar ertelenmesini sağlayın. WorkManager için aşağıdaki kısıtlamalar kullanılabilir:

NetworkType Çalışmanızın yürütülmesi için gereken ağ türünü kısıtlar. Örneğin, Wi-Fi (UNMETERED).
BatteryNotLow Doğru olarak ayarlandığında, cihazın pil seviyesi düşükse çalışmanız çalışmaz.
RequiresCharging Doğru olarak ayarlandığında çalışmanız yalnızca cihaz şarj olurken çalışır.
DeviceIdle Doğru olarak ayarlandığında, işin çalıştırılabilmesi için kullanıcının cihazının boşta olması gerekir. Bu, aksi takdirde kullanıcının cihazında etkin olarak çalışan diğer uygulamalar üzerinde olumsuz bir performans etkisi yaratabilecek toplu işlemleri çalıştırmak için yararlı olabilir.
StorageNotLow Doğru olarak ayarlandığında, kullanıcının cihazındaki depolama alanı çok düşükse çalışmanız çalışmaz.

Bir dizi kısıtlama oluşturup bunları bir işle ilişkilendirmek için Constraints kullanarak bir Constraints.Builder() örneği oluşturun ve bunu WorkRequest.Builder() öğenize atayın.

Örneğin, aşağıdaki kod yalnızca kullanıcının cihazı hem şarj olurken hem de kablosuz bağlantıya 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.

Çalışmanız yürütülürken bir kısıtlama karşılanmazsa WorkManager, çalışanınızı durdurur. Tüm kısıtlamalar karşılandığında iş yeniden denenir.

Rötarlı Çalışma

Çalışmanızın herhangi bir kısıtlaması yoksa veya çalışmanız sıraya alındığında tüm kısıtlamalar karşılanıyorsa sistem, çalışmayı hemen çalıştırmayı seçebilir. İşin hemen çalıştırılmasını istemiyorsanız işinizin minimum başlangıç gecikmesinden sonra başlamasını belirtebilirsiniz.

Çalışmanızın, sıraya alındıktan sonra en az 10 dakika çalışacak şekilde nasıl ayarlanacağına dair bir örneği aşağıda bulabilirsiniz.

Kotlin

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

Java

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

Örnekte OneTimeWorkRequest için ilk gecikmenin nasıl ayarlanacağı gösterilse de PeriodicWorkRequest için de ilk gecikme ayarlayabilirsiniz. Bu durumda, yalnızca periyodik çalışmanızın ilk çalıştırması gecikir.

Yeniden deneme ve geri yükleme aralığı politikası

WorkManager'ın çalışmanızı yeniden denemesini istiyorsanız işçinizden Result.retry() değerini döndürebilirsiniz. Çalışmanız daha sonra geri yükleme aralığı gecikmesi ve geri çekilme politikasına göre yeniden planlanır.

  • Geri çekilme gecikmesi, ilk denemeden sonra çalışmanızı yeniden denemeden önce beklemeniz gereken minimum süreyi belirtir. Bu değer 10 saniyeden (veya MIN_BACKOFF_MILLIS) az olamaz.

  • Geri çekilme politikası, sonraki yeniden deneme girişimlerinde geri çekilme gecikmesinin zaman içinde nasıl artacağını tanımlar. WorkManager, 2 geri yükleme aralığı politikasını destekler: LINEAR ve EXPONENTIAL.

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

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

Kotlin

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

Java

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

Bu örnekte, minimum geri yükleme aralığı, izin verilen minimum değer olan 10 saniyeye ayarlanmıştır. Politika LINEAR olduğundan, yeniden deneme aralığı her yeni denemede yaklaşık 10 saniye artar. Örneğin, Result.retry() ile biten ilk çalıştırma 10 saniye sonra tekrar denenir. İş sonraki denemelerde Result.retry() döndürmeye devam ederse 20, 30, 40 vb. saniye sonra tekrar denenir. Geri çekilme politikası EXPONENTIAL olarak ayarlanırsa yeniden deneme süresi sırası 20, 40 ve 80'e daha yakın olur.

İş yerlerini etiketleme

Her iş isteğinin benzersiz bir tanımlayıcısı vardır. Bu tanımlayıcı, işi daha sonra tanımlamak, iptal etmek veya ilerlemesini gözlemlemek için kullanılabilir.

Mantıksal olarak ilişkili bir iş grubunuz varsa bu iş öğelerini etiketlemek de faydalı olabilir. 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 kodda, çalışmanıza nasıl "temizleme" etiketi ekleyebileceğiniz gösterilmektedir:

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. Dahili olarak bu etiketler bir dizi dize olarak depolanır. WorkRequest ile ilişkili etiket grubunu almak için WorkInfo.getTags() kullanabilirsiniz.

Worker sınıfınızdan, ListenableWorker.getTags() kullanarak etiket grubunu alabilirsiniz.

Giriş verilerini atama

İşiniz için giriş verileri gerekebilir. Örneğin, bir resmi yüklemeyi işleyen bir işlem için, yüklenen resmin URI'sinin giriş olarak sağlanması gerekebilir.

Giriş değerleri, Data nesnesinde anahtar/değer çiftleri olarak depolanır ve iş isteğinde ayarlanabilir. WorkManager, çalışmayı yürüttüğünde girişi Data çalışmanıza iletir. Worker sınıfı, Worker.getInputData() işlevini çağırarak giriş bağımsız değişkenlerine erişebilir. Aşağıdaki kodda, giriş verileri gerektiren bir Worker örneğini nasıl oluşturabileceğiniz ve bunu iş isteğinizde nasıl gönderebileceğiniz 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, bir dönüş değeri oluşturmak için Data sınıfını kullanabilirsiniz.

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.