[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-background-tasks-in-flutter-con-workmanager-eseguire-codice-in-background-su-android-e-ios":3,"comments-article-background-tasks-in-flutter-con-workmanager-eseguire-codice-in-background-su-android-e-ios":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},21,"Background tasks in Flutter con WorkManager: eseguire codice in background su Android e iOS","background-tasks-in-flutter-con-workmanager-eseguire-codice-in-background-su-android-e-ios","Scopri come eseguire attività in background in Flutter usando il plugin workmanager: sincronizzazioni periodiche, task one-off e best practice per Android e iOS.","## Perché servono i background task\n\nMolte app moderne hanno bisogno di eseguire lavoro anche quando l'utente non sta interagendo con l'interfaccia: sincronizzare dati con un server, scaricare contenuti, inviare log, aggiornare una cache. In Flutter, l'isolate principale viene sospeso quando l'app passa in background, quindi non possiamo semplicemente lasciare un `Timer` in esecuzione.\n\nLa soluzione è affidarsi alle API native di scheduling del sistema operativo. Il plugin [`workmanager`](https:\u002F\u002Fpub.dev\u002Fpackages\u002Fworkmanager) fa da ponte verso **WorkManager** su Android e **BGTaskScheduler \u002F performFetchWithCompletionHandler** su iOS, permettendoci di registrare task che il sistema esegue rispettando i vincoli di batteria e rete.\n\n## Installazione\n\nAggiungiamo la dipendenza:\n\n```yaml\ndependencies:\n  workmanager: ^0.5.2\n```\n\n## Il callback dispatcher\n\nIl punto cruciale è che il task viene eseguito in un **isolate separato**, senza accesso allo stato dell'app in memoria. Per questo serve una funzione di top-level (o statica) annotata con `@pragma('vm:entry-point')`, necessaria affinché il codice non venga rimosso dal tree shaking in release.\n\n```dart\nimport 'package:workmanager\u002Fworkmanager.dart';\n\n@pragma('vm:entry-point')\nvoid callbackDispatcher() {\n  Workmanager().executeTask((task, inputData) async {\n    switch (task) {\n      case 'sync-data':\n        await _eseguiSincronizzazione(inputData);\n        break;\n      case 'cleanup-cache':\n        await _pulisciCache();\n        break;\n    }\n    \u002F\u002F true = task completato con successo\n    \u002F\u002F false = il sistema riproverà seci sono criteri di retry\n    return Future.value(true);\n  });\n}\n```\n\n## Inizializzazione\n\nL'inizializzazione va fatta nel `main`, prima di avviare l'app:\n\n```dart\nFuture\u003Cvoid> main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n\n  await Workmanager().initialize(\n    callbackDispatcher,\n    isInDebugMode: true, \u002F\u002F notifiche di debug, da disattivare in release\n  );\n\n  runApp(const MyApp());\n}\n```\n\n## Registrare un task one-off\n\nUn task che deve essere eseguito una sola volta, con eventuali vincoli:\n\n```dart\nawait Workmanager().registerOneOffTask(\n  'task-unico-1',       \u002F\u002F identificatore univoco\n  'sync-data',          \u002F\u002F nome usato nello switch\n  inputData: {'userId': 42},\n  initialDelay: const Duration(seconds: 10),\n  constraints: Constraints(\n    networkType: NetworkType.connected,\n    requiresBatteryNotLow: true,\n  ),\n);\n```\n\n## Task periodici\n\nPer le sincronizzazioni ricorrenti usiamo `registerPeriodicTask`. Attenzione: su Android l'intervallo minimo imposto dal sistema è di **15 minuti**, e iOS non garantisce una cadenza precisa ma decide in base ai pattern di utilizzo.\n\n```dart\nawait Workmanager().registerPeriodicTask(\n  'task-periodico-1',\n  'sync-data',\n  frequency: const Duration(hours: 1),\n  constraints: Constraints(\n    networkType: NetworkType.unmetered, \u002F\u002F solo Wi-Fi\n  ),\n);\n```\n\n## Annullare i task\n\n```dart\n\u002F\u002F Annulla un task specifico\nawait Workmanager().cancelByUniqueName('task-periodico-1');\n\n\u002F\u002F Annulla tutti i task registrati\nawait Workmanager().cancelAll();\n```\n\n## Configurazione iOS\n\nSu iOS il setup richiede passaggi aggiuntivi. Nel file `Info.plist` bisogna abilitare le modalità di background:\n\n```xml\n\u003Ckey>BGTaskSchedulerPermittedIdentifiers\u003C\u002Fkey>\n\u003Carray>\n  \u003Cstring>com.tuodominio.app.sync\u003C\u002Fstring>\n\u003C\u002Farray>\n\u003Ckey>UIBackgroundModes\u003C\u002Fkey>\n\u003Carray>\n  \u003Cstring>fetch\u003C\u002Fstring>\n  \u003Cstring>processing\u003C\u002Fstring>\n\u003C\u002Farray>\n```\n\nE nell'`AppDelegate.swift` va registrato l'identificatore:\n\n```swift\nUIApplication.shared.setMinimumBackgroundFetchInterval(\n  TimeInterval(60 * 15)\n)\n```\n\n## Best practice\n\n- **Mantieni i task brevi**: il sistema concede una finestra di esecuzione limitata. Operazioni troppo lunghe vengono terminate.\n- **Inizializza tutto nel callback**: l'isolate è isolato, quindi devi reinizializzare database, client HTTP e dipendenze dentro `executeTask`.\n- **Gestisci gli errori**: ritorna `false` per sfruttare la logica di retry, ma evita loop infiniti su errori non recuperabili.\n- **Non aspettarti precisione su iOS**: usa i background task per lavoro opportunistico, non per logiche critiche con scadenze rigide.\n- **Testa su dispositivo reale**: gli emulatori e le ottimizzazioni del produttore (es. Doze mode) influenzano l'esecuzione.\n\n## Conclusioni\n\nIl plugin `workmanager` offre un'astrazione comoda sulle API native di scheduling, ideale per sincronizzazioni in background e manutenzione periodica. La chiave è progettare task idempotenti, brevi e indipendenti dallo stato dell'app, ricordando sempre i vincoli imposti dai sistemi operativi su batteria e rete.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fda98b41c-3f62-4fae-9263-04db093093a1.jpg",null,"published","2026-06-25T04:00:35+00:00","Background task in Flutter con WorkManager","Guida pratica all'esecuzione di task in background in Flutter con il plugin workmanager: setup Android\u002FiOS, task periodici e best practice.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219604845]