WorkManager è una libreria Android Jetpack progettata per eseguire attività differite e in background con esecuzione garantita. A differenza di Service o JobScheduler, WorkManager gestisce il ciclo di vita dell'attività: la riavvia in caso di errore, si adatta alla versione di Android e tiene conto dei vincoli del dispositivo. Secondo Android Developers, 2026, WorkManager è la soluzione preferita per la maggior parte delle operazioni in background nello sviluppo Android moderno.
Punti chiave
WorkManager fa parte di Android Jetpack, una libreria per gestire attività in background che devono essere eseguite in modo garantito, indipendentemente dal fatto che l'app sia in primo piano o sia stata chiusa dall'utente. La libreria supporta API 14+ e seleziona automaticamente il meccanismo di esecuzione appropriato: JobScheduler su Android 5+, BroadcastReceiver + AlarmManager su versioni precedenti.
La caratteristica principale di WorkManager è l'esecuzione garantita. Se un'attività non è stata completata a causa di un riavvio del dispositivo, chiusura dell'app o arresto anomalo, WorkManager la riavvierà alla prima occasione. Questo rende la libreria una scelta ideale per attività critiche: invio di analisi, sincronizzazione del database, caricamento dei log.
A differenza di Background Service, WorkManager non richiede gestione di thread e ciclo di vita. La libreria stessa crea un pool di thread, gestisce la Doze Mode, tiene conto della versione di Android e fornisce un'API unificata indipendentemente dal livello API. Il supporto per coroutine e RxJava è disponibile rispettivamente tramite CoroutineWorker e RxWorker.
WorkManager fornisce supporto integrato per LiveData per tracciare lo stato delle attività. Il metodo getWorkInfoByIdLiveData restituisce LiveData<WorkInfo> che si aggiorna ad ogni cambiamento di stato: ENQUEUED, RUNNING, SUCCEEDED, FAILED, CANCELLED. Ciò consente ai componenti dell'interfaccia utente di reagire ai cambiamenti senza polling manuale del pianificatore e senza perdite di memoria grazie ai componenti Lifecycle-aware.
WorkManager.getInstance(context)
.getWorkInfoByIdLiveData(syncRequest.id)
.observe(viewLifecycleOwner) { workInfo ->
when (workInfo.state) {
WorkInfo.State.SUCCEEDED ->
showSuccess()
WorkInfo.State.FAILED ->
showError(workInfo.outputData)
else ->
showProgress()
}
}
L'architettura di WorkManager è costruita attorno a tre classi base: Worker, WorkRequest e WorkManager. Worker contiene la logica dell'attività, WorkRequest descrive i parametri di esecuzione e WorkManager gestisce la coda e la pianificazione. La libreria utilizza un database Room interno per memorizzare lo stato di tutte le attività.
Worker è una classe astratta con un singolo metodo doWork che viene chiamato su un thread in background. Il metodo restituisce ListenableWorker.Result — SUCCESS, FAILURE o RETRY. WorkRequest collega il Worker con i parametri: timeout, tag, ritardo iniziale e vincoli.
class SyncWorker(
context: Context,
params: WorkerParameters
) : Worker(context, params) {
override fun doWork(): Result {
return try {
val api = RetrofitClient.api
val response = api.syncData()
Result.success()
} catch (e: Exception) {
Result.retry()
}
}
}
WorkManager pianifica le attività in modo uniforme indipendentemente dalla versione di Android. Quando si chiama enqueue, la libreria salva l'attività in Room, valuta le condizioni attuali e seleziona il momento di esecuzione ottimale. Sotto il cofano, può utilizzare JobScheduler, AlarmManager o il proprio pianificatore — lo sviluppatore non deve preoccuparsene.
val syncRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setInitialDelay(15, TimeUnit.MINUTES)
.addTag("sync")
.build()
WorkManager.getInstance(context)
.enqueue(syncRequest)
WorkManager supporta due tipi di richieste di esecuzione: una tantum e periodiche. La scelta del tipo dipende dallo scenario: l'attività deve essere eseguita una volta o ripetuta a un intervallo specificato.
OneTimeWorkRequest è progettato per attività che devono essere eseguite una sola volta. Può essere l'invio di un log, la sincronizzazione dei dati dopo l'autorizzazione, il download della configurazione al primo avvio. Il ritardo viene impostato tramite setInitialDelay e i vincoli tramite setConstraints.
PeriodicWorkRequest è adatto per attività ripetitive con un intervallo minimo di 15 minuti. La libreria garantisce che l'intervallo tra le esecuzioni non sarà inferiore a quello specificato, ma potrebbe essere più lungo a causa dei vincoli del dispositivo. Per attività con frequenza inferiore a 15 minuti, utilizzare Handler o Timer in Foreground Service.
| Parametro | OneTimeWorkRequest | PeriodicWorkRequest |
|---|---|---|
| Frequenza | una tantum | ripetuta (min. 15 min) |
| Quantità | 1 esecuzione | fino ad annullamento |
| Ritardo | setInitialDelay | setInitialDelay |
| Catene | supporta | no |
| Utilizzo | download, sincronizzazione | monitoraggio, polling |
I vincoli in WorkManager consentono di impostare le condizioni in cui un'attività può essere avviata: connessione di rete (NetworkType), livello della batteria (batteryNotLow), stato dell'archiviazione (StorageNotLow) e modalità inattiva (DeviceIdle). L'attività non verrà avviata fino a quando tutti i vincoli non saranno soddisfatti.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(true)
.setRequiresBatteryNotLow(true)
.build()
val request = OneTimeWorkRequestBuilder<ImageUploadWorker>()
.setConstraints(constraints)
.build()
Le catene consentono di organizzare l'esecuzione sequenziale o parallela delle attività. beginWith avvia una catena, then aggiunge il Worker successivo che verrà eseguito dopo il completamento con successo del precedente. Per l'esecuzione parallela, utilizzare workManager.enqueue(listOf(request1, request2)).
WorkManager.getInstance(context)
.beginWith(compressWorker)
.then(uploadWorker)
.then(cleanupWorker)
.enqueue()
// compress -> upload -> cleanup sequenzialmente
JobScheduler è stato introdotto in Android 5 (API 21) come servizio di sistema per pianificare attività in background. WorkManager è venuto a sostituirlo, offrendo un'API multipiattaforma con migrazione automatica e capacità aggiuntive: catene, garanzia di esecuzione, tag, osservazione dello stato tramite LiveData.
Quando si migra da JobScheduler a WorkManager, è necessario convertire JobService in Worker, sostituire JobInfo con WorkRequest e Context.getSystemService con l'API di WorkManager. WorkManager gestisce automaticamente i problemi di compatibilità e gestisce la Doze Mode in modo più corretto rispetto a un'implementazione manuale di JobScheduler. Fasi della migrazione: 1) creare una classe Worker, 2) costruire un WorkRequest con le stesse condizioni, 3) rimuovere JobService e JobInfo dal codice e dal manifest.
WorkManager supporta il concetto di attività uniche tramite ExistingWorkPolicy. Se esiste già un'attività con il nome specificato, la politica determina il comportamento: KEEP (non crearne una nuova), REPLACE (sostituire quella esistente), APPEND (aggiungere alla fine della catena) e APPEND_OR_REPLACE. UniqueWorkRequest è comodo per attività che non devono essere duplicate: sincronizzazione del database, download della configurazione, invio batch di analisi.
WorkManager.getInstance(context)
.enqueueUniqueWork(
"sync_data",
ExistingWorkPolicy.KEEP,
syncRequest
)
CoroutineWorker supporta il meccanismo setProgress, consentendo di passare risultati di esecuzione intermedi. Ciò è utile per operazioni lunghe: download di file grandi, elaborazione batch di immagini, migrazione del database. L'interfaccia utente può iscriversi agli aggiornamenti tramite getWorkInfosByTagLiveData e visualizzare l'avanzamento in tempo reale. Il metodo ForegroundInfo è inoltre disponibile per eseguire un Worker come Foreground Service con una notifica se l'attività deve essere visibile all'utente.
class ProgressWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val total = 100
for (i in 1..total) {
setProgress(
workDataOf("progress" to i)
)
}
return Result.success()
}
}
WorkManager supporta il trasferimento di dati tra Worker tramite InputData e OutputData. InputData viene creato durante la costruzione di WorkRequest tramite Data.Builder e viene passato al Worker tramite inputData. Dopo l'esecuzione, il Worker crea OutputData tramite workDataOf o Data.Builder e lo restituisce insieme a Result.success(outputData). Il Worker successivo nella catena riceve l'outputData del precedente come proprio inputData. I dati vengono memorizzati in formato chiave-valore con supporto per i tipi base: String, Int, Long, Boolean, Double. La dimensione massima di Data è 10 KB.
In pratica, molti progetti utilizzano WorkManager come unico pianificatore di attività in background. Google raccomanda di migrare tutti i JobService esistenti a WorkManager, specialmente nelle app che supportano Android 4.4 (API 19) e inferiori, dove JobScheduler non è disponibile e WorkManager utilizza un meccanismo di fallback tramite AlarmManager e BroadcastReceiver. Per i test, WorkManager fornisce TestListenableWorkerBuilder e TestWorkerBuilder, che consentono di testare i Worker in test JUnit senza un pianificatore reale.
Per testare WorkManager, utilizzare TestListenableWorkerBuilder da AndroidX Test, che consente di eseguire Worker in un ambiente isolato e verificare il Result restituito. La libreria fornisce supporto completo per JUnit e Robolectric per test unitari senza un pianificatore reale. Nel complesso, WorkManager è adatto all'80% delle attività dove prima venivano utilizzati Service o JobScheduler.
Domande frequenti
Sì, WorkManager garantisce l'esecuzione anche dopo il riavvio. La libreria salva tutte le attività incomplete in un database Room e le ripristina utilizzando BroadcastReceiver che si attiva dopo l'avvio del sistema.
Worker viene eseguito su un thread in background senza supporto di coroutine o RxJava. CoroutineWorker utilizza le coroutine Kotlin con supporto per funzioni suspend e annullamento tramite ambito di coroutine. RxWorker funziona con Observable e Single, adatto per catene reattive.
Utilizzare workManager.cancelWorkById(id) o workManager.cancelAllWorkByTag("tag"). La libreria fornisce anche il metodo cancelUniqueWork("name") per annullare attività uniche con il nome specificato.
L'intervallo minimo per PeriodicWorkRequest è di 15 minuti. Questa limitazione è stata imposta da Google per prevenire un consumo eccessivo della batteria. Se un'attività deve essere eseguita più frequentemente, utilizzare Foreground Service o Handler con un timer.
Sì, WorkManager supporta API 14+. Su dispositivi senza JobScheduler (inferiore a API 21), la libreria utilizza una combinazione di AlarmManager e BroadcastReceiver per la pianificazione delle attività. Questo rende WorkManager una soluzione universale per le attività in background.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche