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.
Ş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
veEXPONENTIAL
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.