Worker
ve WorkRequest
tanımladıktan sonraki son adım, çalışmanızı sıraya almak olacaktır. İşleri sıraya almanın 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);
Çalışmaları sıraya alırken yinelemeyi önlemek için dikkatli olun. Örneğin, bir uygulama günlüklerini her 24 saatte bir arka uç hizmetine yüklemeye çalışabilir. Dikkatli olmazsanız işin yalnızca bir kez çalışması gerekmesine rağmen aynı görevi birçok kez sıraya alabilirsiniz. Bu hedefe ulaşmak için işi benzersiz iş olarak planlayabilirsiniz.
Benzersiz Çalışma
Benzersiz çalışma, belirli bir adla aynı anda yalnızca bir çalışma örneğine sahip olmanızı garanti eden güçlü bir kavramdır. Kimliklerin aksine, benzersiz adlar insanlar tarafından okunabilir ve WorkManager tarafından otomatik olarak oluşturulmak yerine geliştirici tarafından belirtilir. Benzersiz adlar, etiketlerin aksine yalnızca tek bir çalışma örneğiyle ilişkilendirilir.
Benzersiz çalışma hem tek seferlik hem de düzenli çalışmalara uygulanabilir. Tekrarlanan bir iş veya tek seferlik bir iş planlamanıza bağlı olarak bu yöntemlerden birini çağırarak benzersiz bir iş sırası oluşturabilirsiniz.
WorkManager.enqueueUniqueWork()
tek seferlik iş için- Dönemsel çalışma için
WorkManager.enqueueUniquePeriodicWork()
Bu yöntemlerin her ikisi de 3 bağımsız değişken kabul eder:
- uniqueWorkName: Çalışma isteğini benzersiz şekilde tanımlamak için kullanılan
String
. - existingWorkPolicy - Bu benzersiz ada sahip, tamamlanmamış bir iş zinciri zaten varsa WorkManager'a ne yapması gerektiğini söyleyen bir
enum
. Daha fazla bilgi için çakışma çözümü politikasına bakın. - work: Planlanacak
WorkRequest
.
Benzersiz çalışmalar kullanarak daha önce belirtilen yinelenen planlama sorunumuzu düzeltebiliriz.
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 zaten kuyruktayken kod çalıştırılırsa mevcut iş korunur ve yeni bir iş eklenmez.
Uzun bir görev zinciri oluşturmanız gerektiğinde benzersiz iş sıraları da faydalı olabilir. Örneğin, bir fotoğraf düzenleme uygulaması, kullanıcıların uzun bir işlem zincirini geri almasına olanak tanıyabilir. Bu geri alma işlemlerinin her biri biraz zaman alabilir ancak doğru sırayla gerçekleştirilmeleri gerekir. Bu durumda uygulama, bir "geri alma" zinciri oluşturabilir ve her geri alma işlemini gerektiği gibi zincire ekleyebilir. Daha fazla bilgi için Çalışmaları zincirleme bölümüne bakın.
Çatışma çözümü politikası
Benzersiz bir iş planlarken WorkManager'a çakışma olduğunda hangi işlemi yapması gerektiğini söylemeniz gerekir. Bunu, işi sıraya alırken bir enum ileterek yaparsınız.
Tek seferlik işler için ExistingWorkPolicy
sağlarsınız. Bu ExistingWorkPolicy
, çakışmayı yönetmek için 4 seçeneği destekler.
REPLACE
mevcut çalışmayı yeni çalışmayla karşılaştırın. Bu seçenek, mevcut çalışmayı iptal eder.KEEP
mevcut çalışmayı ve yeni çalışmayı yoksay.APPEND
yeni çalışmayı mevcut çalışmanın sonuna. Bu politika, yeni çalışmanızın mevcut çalışmaya bağlanmasına ve mevcut çalışma tamamlandıktan sonra çalışmasına neden olur.
Mevcut çalışma, yeni çalışmanın ön koşulu haline gelir. Mevcut çalışma CANCELLED
veya FAILED
olursa yeni çalışma da CANCELLED
veya FAILED
olur.
Yeni işin mevcut işin durumundan bağımsız olarak çalışmasını istiyorsanız bunun yerine APPEND_OR_REPLACE
kullanın.
APPEND_OR_REPLACE
,APPEND
ile benzer şekilde çalışır ancak ön koşul iş durumuyla ilişkili değildir. Mevcut çalışmaCANCELLED
veyaFAILED
ise yeni çalışma yine de çalışır.
Dönemlik çalışmalarda, REPLACE
ve KEEP
olmak üzere 2 seçeneği destekleyen bir ExistingPeriodicWorkPolicy
sağlarsınız. Bu seçenekler, ExistingWorkPolicy karşılıklarıyla aynı şekilde çalışır.
Çalışmanızı gözlemleme
Çalışma sıraya alındıktan sonra, name
, id
veya ilişkili bir tag
ile WorkManager'ı sorgulayarak durumunu istediğiniz zaman 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, ListenableFuture
WorkInfo
nesnesini döndürür. Bu nesne, çalışmanın id
, etiketleri, mevcut State
ve Result.success(outputData)
kullanan tüm çıkış veri kümelerini içerir.
Her yöntemin LiveData
ve Flow
varyantları, bir dinleyici kaydederek WorkInfo
değişikliklerini gözlemlemenizi sağlar. Örneğin, bazı işlemler başarıyla tamamlandığında kullanıcıya mesaj göstermek istiyorsanız bunu aşağıdaki gibi ayarlayabilirsiniz:
Kotlin
workManager.getWorkInfoByIdFlow(syncWorker.id)
.collect{ 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
nesneleri kullanılarak sıraya alınmış işler için karmaşık sorgulamayı destekler. WorkQuery, etiketleri, durumu ve benzersiz iş adının kombinasyonuyla iş sorgulamayı destekler.
Aşağıdaki örnekte, FAILED
veya CANCELLED
durumunda olan ve"preProcess" ya da "sync" şeklinde benzersiz bir çalışma adına sahip "syncTag" etiketli 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);
Bir WorkQuery
içindeki her bileşen (etiket, durum veya ad), diğerleriyle AND
. Bir bileşendeki her değer OR
ile ayrılır. Örneğin: (name1 OR name2
OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)
.
WorkQuery
, LiveData eşdeğeri olan
getWorkInfosLiveData()
ve Flow eşdeğeri olan getWorkInfosFlow()
ile de çalışır.
Çalışmayı iptal etme ve durdurma
Daha önce sıraya aldığınız işinizin artık çalıştırılmasına gerek yoksa iptal edilmesini isteyebilirsiniz. Çalışma, name
, id
veya 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 çalışmanın State
olup olmadığını kontrol eder. Çalışma tamamlanmışsa
hiçbir şey olmaz. Aksi takdirde, işin durumu CANCELLED
olarak değiştirilir ve iş gelecekte çalışmaz. WorkRequest
işleri bu çalışmaya bağımlıysa onlar da CANCELLED
olur.
RUNNING
çalışanı
ListenableWorker.onStopped()
numaralı telefondan
arama alıyor.
Olası temizleme işlemlerini gerçekleştirmek için bu yöntemi geçersiz kılın. Daha fazla bilgi için çalışan bir işi durdurma başlıklı makaleyi inceleyin.
Çalışan bir Worker'ı durdurma
Çalışan Worker
'nızın WorkManager tarafından durdurulmasının birkaç nedeni olabilir:
- İptal edilmesini açıkça istediniz (örneğin,
WorkManager.cancelWorkById(UUID)
numaralı telefonu arayarak). - Benzersiz çalışma durumunda,
REPLACE
ExistingWorkPolicy
ile yeni birWorkRequest
açıkça sıraya alınır. EskiWorkRequest
hemen iptal edilmiş olarak kabul edilir. - Çalışmanızın kısıtlamaları artık karşılanmıyor.
- Sistem, uygulamanıza çalışmayı durdurmasını söyledi. Bu durum, 10 dakikalık yürütme son tarihini aşarsanız meydana gelebilir. İşin daha sonra yeniden denenmesi planlanıyor.
Bu koşullar altında Worker'ınız durdurulur.
Devam eden tüm çalışmaları işbirliği içinde durdurmalı ve Worker'ınızın tuttuğu tüm kaynakları serbest bırakmalısınız. Örneğin, bu noktada veritabanları ve dosyalar için açık tutulan tutmaç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, Worker'ınız durdurulur durdurulmaz ListenableWorker.onStopped()
'ı çağırır. Elde tuttuğunuz 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. Worker'ınızda uzun süren veya tekrarlanan işlemler gerçekleştiriyorsanız bu özelliği sık sık kontrol etmeli ve mümkün olan en kısa sürede çalışmayı durdurmak için bir sinyal olarak kullanmalısınız.
Not: WorkManager, onStop sinyalini almış bir Worker tarafından ayarlanan Result
değerini yoksayar. Bunun nedeni, Worker'ın zaten durdurulmuş olarak kabul edilmesidir.
Durdurma nedeni durumunu gözlemleme
Worker
öğesinin neden durdurulduğunu ayıklamak için WorkInfo.getStopReason()
işlevini çağırarak durdurma nedenini günlüğe kaydedebilirsiniz:
Kotlin
workManager.getWorkInfoByIdFlow(syncWorker.id)
.collect { workInfo ->
if (workInfo != null) {
val stopReason = workInfo.stopReason
logStopReason(syncWorker.id, stopReason)
}
}
Java
workManager.getWorkInfoByIdLiveData(syncWorker.id)
.observe(getViewLifecycleOwner(), workInfo -> {
if (workInfo != null) {
int stopReason = workInfo.getStopReason();
logStopReason(syncWorker.id, workInfo.getStopReason());
}
});