[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-persistenza-dei-dati-in-flutter-con-drift-il-database-reattivo":3,"comments-article-persistenza-dei-dati-in-flutter-con-drift-il-database-reattivo":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},4,"Persistenza dei dati in Flutter con Drift: il database reattivo","persistenza-dei-dati-in-flutter-con-drift-il-database-reattivo","Scopri come gestire un database SQLite locale in Flutter usando Drift, la libreria type-safe e reattiva che semplifica query, migrazioni e integrazione con lo stato dell'app.","## Perché Drift per la persistenza locale\n\nQuando un'applicazione Flutter ha bisogno di salvare dati strutturati in locale — pensiamo a una to-do list offline, a una cache complessa o a un'app di tracking — `SharedPreferences` non basta. In questi casi serve un vero database SQLite, e **Drift** (l'evoluzione di Moor) è oggi una delle scelte più solide.\n\nDrift offre tre vantaggi chiave:\n\n- **Type-safety**: le query vengono validate a tempo di compilazione, niente più errori SQL scoperti a runtime.\n- **Reattività**: puoi osservare le query come `Stream`, aggiornando automaticamente la UI quando i dati cambiano.\n- **Cross-platform**: funziona su mobile, desktop e web.\n\n## Installazione\n\nAggiungi le dipendenze al `pubspec.yaml`:\n\n```yaml\ndependencies:\n  drift: ^2.18.0\n  sqlite3_flutter_libs: ^0.5.0\n  path_provider: ^2.1.0\n  path: ^1.9.0\n\ndev_dependencies:\n  drift_dev: ^2.18.0\n  build_runner: ^2.4.0\n```\n\n## Definire una tabella\n\nIn Drift le tabelle sono classi Dart. Definiamo una tabella `Todos`:\n\n```dart\nimport 'package:drift\u002Fdrift.dart';\n\nclass Todos extends Table {\n  IntColumn get id => integer().autoIncrement()();\n  TextColumn get title => text().withLength(min: 1, max: 100)();\n  TextColumn get description => text().nullable()();\n  BoolColumn get completed => boolean().withDefault(const Constant(false))();\n  DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();\n}\n```\n\n## Creare il database\n\nLa classe del database collega le tabelle e gestisce la connessione:\n\n```dart\nimport 'dart:io';\nimport 'package:drift\u002Fdrift.dart';\nimport 'package:drift\u002Fnative.dart';\nimport 'package:path_provider\u002Fpath_provider.dart';\nimport 'package:path\u002Fpath.dart' as p;\n\npart 'database.g.dart';\n\n@DriftDatabase(tables: [Todos])\nclass AppDatabase extends _$AppDatabase {\n  AppDatabase() : super(_openConnection());\n\n  @override\n  int get schemaVersion => 1;\n}\n\nLazyDatabase _openConnection() {\n  return LazyDatabase(() async {\n    final dir = await getApplicationDocumentsDirectory();\n    final file = File(p.join(dir.path, 'app.db'));\n    return NativeDatabase.createInBackground(file);\n  });\n}\n```\n\nGenera il codice con:\n\n```bash\ndart run build_runner build\n```\n\n## Operazioni CRUD\n\nDrift genera automaticamente le classi dei dati. Ecco i metodi principali da aggiungere alla classe `AppDatabase`:\n\n```dart\n\u002F\u002F Lettura reattiva: la UI si aggiorna da sola\nStream\u003CList\u003CTodo>> watchAllTodos() => select(todos).watch();\n\n\u002F\u002F Inserimento\nFuture\u003Cint> addTodo(TodosCompanion entry) => into(todos).insert(entry);\n\n\u002F\u002F Aggiornamento\nFuture\u003Cbool> updateTodo(Todo todo) => update(todos).replace(todo);\n\n\u002F\u002F Eliminazione\nFuture\u003Cint> deleteTodo(int id) =>\n    (delete(todos)..where((t) => t.id.equals(id))).go();\n```\n\nPer inserire un nuovo elemento si usa il `Companion`, che distingue i campi presenti da quelli assenti:\n\n```dart\nawait db.addTodo(\n  TodosCompanion.insert(\n    title: 'Studiare Drift',\n    description: const Value('Leggere la documentazione'),\n  ),\n);\n```\n\n## Mostrare i dati con StreamBuilder\n\nGrazie alla reattività, basta uno `StreamBuilder` per avere una lista sempre aggiornata:\n\n```dart\nStreamBuilder\u003CList\u003CTodo>>(\n  stream: db.watchAllTodos(),\n  builder: (context, snapshot) {\n    if (!snapshot.hasData) {\n      return const Center(child: CircularProgressIndicator());\n    }\n    final todos = snapshot.data!;\n    return ListView.builder(\n      itemCount: todos.length,\n      itemBuilder: (context, i) {\n        final todo = todos[i];\n        return CheckboxListTile(\n          title: Text(todo.title),\n          value: todo.completed,\n          onChanged: (val) => db.updateTodo(\n            todo.copyWith(completed: val ?? false),\n          ),\n        );\n      },\n    );\n  },\n)\n```\n\n## Gestire le migrazioni\n\nQuando lo schema cambia, incrementa `schemaVersion` e definisci la strategia di migrazione:\n\n```dart\n@override\nMigrationStrategy get migration => MigrationStrategy(\n  onUpgrade: (migrator, from, to) async {\n    if (from \u003C 2) {\n      await migrator.addColumn(todos, todos.priority);\n    }\n  },\n);\n```\n\n## Conclusione\n\nDrift unisce la potenza di SQLite alla sicurezza dei tipi di Dart e a un modello reattivo che si integra naturalmente con l'architettura di Flutter. È la soluzione ideale quando hai bisogno di query complesse, relazioni e persistenza affidabile, mantenendo al tempo stesso un codice pulito e verificato a compile-time. Se la tua app cresce oltre le semplici preferenze, Drift è un investimento che ripaga.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F49d640fb-cdb1-4288-95b6-f171a3b0ba10.jpg",null,"published","2026-06-07T06:00:32+00:00","Persistenza dati in Flutter con Drift: guida pratica","Impara a usare Drift in Flutter per gestire un database SQLite reattivo e type-safe: tabelle, CRUD, StreamBuilder e migrazioni spiegati passo passo.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1781247856989]