[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-generazione-di-codice-in-flutter-con-freezed-modelli-immutabili-e-union-types":3,"comments-article-generazione-di-codice-in-flutter-con-freezed-modelli-immutabili-e-union-types":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},42,"Generazione di codice in Flutter con Freezed: modelli immutabili e union types","generazione-di-codice-in-flutter-con-freezed-modelli-immutabili-e-union-types","Scopri come Freezed elimina il boilerplate nella creazione di data class immutabili, copyWith, equality e union types (sealed class) per gestire gli stati in modo sicuro ed elegante.","## Perché Freezed?\n\nScrivere modelli di dati in Dart può diventare rapidamente noioso: per ogni classe dobbiamo implementare manualmente `copyWith`, `==`, `hashCode`, `toString` e magari la serializzazione JSON. Il rischio di errori è alto e il codice diventa verboso.\n\n**Freezed** è un package di code generation che risolve questi problemi generando automaticamente tutto il boilerplate per data class immutabili e union types (le cosiddette *sealed class*). È diventato uno standard di fatto nella community Flutter, soprattutto in combinazione con pattern come BLoC o Riverpod.\n\n## Installazione\n\nAggiungi le dipendenze al `pubspec.yaml`:\n\n```yaml\ndependencies:\n  freezed_annotation: ^2.4.4\n  json_annotation: ^4.9.0\n\ndev_dependencies:\n  build_runner: ^2.4.13\n  freezed: ^2.5.7\n  json_serializable: ^6.8.0\n```\n\n`json_serializable` e `json_annotation` sono opzionali: servono solo se vuoi anche la serializzazione JSON.\n\n## Creare un modello immutabile\n\nCreiamo un modello `User`. Il file deve dichiarare le due `part` che ospiteranno il codice generato:\n\n```dart\nimport 'package:freezed_annotation\u002Ffreezed_annotation.dart';\n\npart 'user.freezed.dart';\npart 'user.g.dart';\n\n@freezed\nclass User with _$User {\n  const factory User({\n    required String id,\n    required String name,\n    @Default(false) bool isPremium,\n    String? email,\n  }) = _User;\n\n  factory User.fromJson(Map\u003CString, dynamic> json) => _$UserFromJson(json);\n}\n```\n\nLancia poi il generatore:\n\n```bash\ndart run build_runner build --delete-conflicting-outputs\n```\n\nCon poche righe otteniamo gratuitamente:\n\n- Un costruttore immutabile con parametri nominali.\n- `copyWith` per creare copie modificate.\n- `==` e `hashCode` basati sui valori.\n- `toString` leggibile.\n- Serializzazione `toJson` \u002F `fromJson`.\n\n## Usare copyWith e l'immutabilità\n\n```dart\nfinal user = User(id: '1', name: 'Anna');\n\n\u002F\u002F Non possiamo modificare user, ma possiamo crearne una copia\nfinal premiumUser = user.copyWith(isPremium: true);\n\nprint(user.isPremium);        \u002F\u002F false\nprint(premiumUser.isPremium); \u002F\u002F true\nprint(user == premiumUser);   \u002F\u002F false (value equality)\n```\n\nGrazie alla value equality generata, due istanze con gli stessi campi risultano uguali, un enorme vantaggio quando confrontiamo stati nell'UI.\n\n## Union types: gestire gli stati in modo sicuro\n\nLa vera forza di Freezed sono le *union* (o sealed class), perfette per rappresentare gli stati di una schermata. Immaginiamo lo stato di una richiesta di rete:\n\n```dart\nimport 'package:freezed_annotation\u002Ffreezed_annotation.dart';\n\npart 'result_state.freezed.dart';\n\n@freezed\nclass ResultState\u003CT> with _$ResultState\u003CT> {\n  const factory ResultState.initial() = Initial\u003CT>;\n  const factory ResultState.loading() = Loading\u003CT>;\n  const factory ResultState.success(T data) = Success\u003CT>;\n  const factory ResultState.error(String message) = Error\u003CT>;\n}\n```\n\nOra possiamo gestire ogni caso in modo esaustivo con `when`, senza dimenticare alcuno stato (sarà il compilatore ad avvisarci):\n\n```dart\nWidget build(BuildContext context) {\n  return state.when(\n    initial: () => const Text('Premi per caricare'),\n    loading: () => const CircularProgressIndicator(),\n    success: (data) => Text('Dati: $data'),\n    error: (message) => Text('Errore: $message'),\n  );\n}\n```\n\n### maybeWhen e map\n\nQuando ci interessa solo un caso, `maybeWhen` fornisce un fallback con `orElse`:\n\n```dart\nfinal isLoading = state.maybeWhen(\n  loading: () => true,\n  orElse: () => false,\n);\n```\n\nEsistono anche le varianti `map`, `maybeMap` e `mapOrNull` che ricevono l'oggetto tipizzato completo invece dei singoli parametri, utili se hai bisogno dell'intera istanza.\n\n## Personalizzazioni utili\n\n- **`@Default`**: assegna un valore di default a un campo.\n- **`@JsonKey(name: 'user_name')`**: mappa un campo JSON con nome diverso.\n- **Metodi custom**: puoi aggiungere getter e metodi tramite un costruttore privato:\n\n```dart\n@freezed\nclass Product with _$Product {\n  const Product._(); \u002F\u002F costruttore privato necessario\n\n  const factory Product({\n    required String name,\n    required double price,\n  }) = _Product;\n\n  String get formattedPrice => '€ ${price.toStringAsFixed(2)}';\n}\n```\n\n## Suggerimenti pratici\n\n- Usa `build_runner watch` durante lo sviluppo per rigenerare automaticamente ad ogni salvataggio.\n- Aggiungi i file `*.freezed.dart` e `*.g.dart` al versionamento se il team non rigenera sempre il codice, altrimenti escludili con `.gitignore`.\n- Con Dart 3 esistono le *sealed class* native con pattern matching, ma Freezed rimane più conciso e offre `copyWith`, serializzazione e deep copy pronti all'uso.\n\n## Conclusione\n\nFreezed riduce drasticamente il boilerplate, rende i modelli immutabili e sicuri, e con le union types offre un modo elegante e a prova di errore per gestire gli stati dell'applicazione. È uno strumento che vale la pena integrare in ogni progetto Flutter di media o grande dimensione.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Ffa86360e-c793-4313-8278-83cd176626f7.jpg",null,"published","2026-07-16T04:00:37+00:00","Freezed in Flutter: modelli immutabili e union types","Guida a Freezed per Flutter: genera data class immutabili, copyWith, equality e union types per gestire gli stati in modo sicuro ed elegante.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1785219601354]