[{"data":1,"prerenderedAt":27},["ShallowReactive",2],{"articolo-asset-type-safe-in-flutter-con-flutter-gen-addio-alle-stringhe-magiche":3,"comments-article-asset-type-safe-in-flutter-con-flutter-gen-addio-alle-stringhe-magiche":26},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"cover_remote_url":10,"cover_credit":11,"video_url":15,"status":16,"published_at":17,"meta_title":18,"meta_description":19,"category":20,"author":24},140,"Asset type-safe in Flutter con flutter_gen: addio alle stringhe magiche","asset-type-safe-in-flutter-con-flutter-gen-addio-alle-stringhe-magiche","Scrivere 'assets\u002Fimages\u002Flogo.png' a mano è una fonte silenziosa di bug. Con flutter_gen generi classi Dart per immagini, SVG, font, Lottie e colori: autocompletamento, errori a compile time e refactoring sicuri.","## Il problema delle stringhe magiche\n\nIn quasi ogni progetto Flutter prima o poi compare una riga come questa:\n\n```dart\nImage.asset('assets\u002Fimages\u002Fprofile_placeholder.png')\n```\n\nFunziona, finché qualcuno non rinomina il file, non sposta la cartella o non sbaglia una lettera. Il compilatore non dice nulla: l'errore arriva a runtime, spesso in produzione, sotto forma di un rettangolo grigio con l'eccezione `Unable to load asset`.\n\nLo stesso vale per i font (`fontFamily: 'Montserrat'`), per i file JSON di configurazione, per le animazioni Lottie e per le icone SVG. Sono tutte dipendenze reali del codice, ma espresse in un formato che nessuno strumento può verificare.\n\n**flutter_gen** risolve il problema alla radice: analizza il `pubspec.yaml` e la cartella degli asset e genera classi Dart tipizzate. Da quel momento `Assets.images.profilePlaceholder` è un simbolo vero, con autocompletamento, *go to definition* e refactoring automatico.\n\n## Installazione e configurazione\n\nflutter_gen non è una dipendenza runtime: è un generatore. Si aggiunge quindi tra le `dev_dependencies`.\n\n```yaml\ndev_dependencies:\n  build_runner: ^2.4.13\n  flutter_gen_runner: ^5.8.0\n```\n\nLa configurazione vive direttamente nel `pubspec.yaml`, sotto la chiave di primo livello `flutter_gen`:\n\n```yaml\nflutter:\n  uses-material-design: true\n  assets:\n    - assets\u002Fimages\u002F\n    - assets\u002Ficons\u002F\n    - assets\u002Flottie\u002F\n    - assets\u002Fjson\u002F\n  fonts:\n    - family: Montserrat\n      fonts:\n        - asset: assets\u002Ffonts\u002FMontserrat-Regular.ttf\n        - asset: assets\u002Ffonts\u002FMontserrat-Bold.ttf\n          weight: 700\n\nflutter_gen:\n  output: lib\u002Fgen\u002F           # dove finiscono i file generati\n  line_length: 80\n\n  integrations:\n    flutter_svg: true        # genera il metodo .svg()\n    lottie: true             # genera il metodo .lottie()\n    rive: true\n\n  assets:\n    enabled: true\n    outputs:\n      class_name: Assets\n      style: dot-delimiter   # Assets.images.logo\n      package_parameter_enabled: false\n\n  fonts:\n    enabled: true\n\n  colors:\n    inputs:\n      - assets\u002Fcolors\u002Fcolors.xml\n```\n\nPer generare il codice:\n\n```bash\ndart run build_runner build --delete-conflicting-outputs\n```\n\nIn alternativa si può installare la CLI globale, utile quando non si vuole far girare l'intera pipeline di build_runner:\n\n```bash\ndart pub global activate flutter_gen\nfluttergen -c pubspec.yaml\n```\n\nIl risultato sono file come `lib\u002Fgen\u002Fassets.gen.dart`, `lib\u002Fgen\u002Ffonts.gen.dart` e `lib\u002Fgen\u002Fcolors.gen.dart`.\n\n## Usare gli asset generati\n\n### Immagini\n\nOgni immagine diventa un oggetto `AssetGenImage` con metodi pronti all'uso:\n\n```dart\nimport 'package:myapp\u002Fgen\u002Fassets.gen.dart';\n\n\u002F\u002F Il path grezzo, se serve\nfinal path = Assets.images.logo.path; \u002F\u002F 'assets\u002Fimages\u002Flogo.png'\n\n\u002F\u002F Widget Image già configurato\nAssets.images.logo.image(\n  width: 120,\n  fit: BoxFit.contain,\n  filterQuality: FilterQuality.medium,\n);\n\n\u002F\u002F ImageProvider, utile per DecorationImage o precaching\nContainer(\n  decoration: BoxDecoration(\n    image: DecorationImage(\n      image: Assets.images.background.provider(),\n      fit: BoxFit.cover,\n    ),\n  ),\n);\n```\n\nLe varianti di risoluzione (`2.0x\u002F`, `3.0x\u002F`) continuano a funzionare esattamente come prima: flutter_gen genera un solo simbolo per l'immagine base, mentre Flutter sceglie a runtime la variante corretta in base al `devicePixelRatio`.\n\n### SVG\n\nCon `flutter_svg: true` nelle integrazioni, i file `.svg` espongono un metodo dedicato:\n\n```dart\nAssets.icons.menu.svg(\n  width: 24,\n  height: 24,\n  colorFilter: ColorFilter.mode(\n    Theme.of(context).colorScheme.onSurface,\n    BlendMode.srcIn,\n  ),\n);\n```\n\nIl pacchetto `flutter_svg` deve ovviamente essere tra le dipendenze del progetto: flutter_gen si limita a generare la chiamata.\n\n### Lottie, Rive e file generici\n\n```dart\n\u002F\u002F Animazione Lottie\nAssets.lottie.loading.lottie(repeat: true);\n\n\u002F\u002F File JSON o qualsiasi altro asset: resta una String tipizzata\nfinal raw = await rootBundle.loadString(Assets.json.remoteConfigDefaults);\n```\n\n### Font\n\n```dart\nimport 'package:myapp\u002Fgen\u002Ffonts.gen.dart';\n\nTextStyle(\n  fontFamily: FontFamily.montserrat,\n  fontWeight: FontWeight.w700,\n);\n```\n\nSe un giorno il designer cambia font e il `family` nel pubspec diventa `Inter`, la rigenerazione fa esplodere a compile time tutti i punti che usavano `FontFamily.montserrat`. È esattamente quello che vogliamo.\n\n### Colori da XML\n\nSe condividi la palette con il team Android (o la esporti da Figma in formato XML), flutter_gen può generarla:\n\n```xml\n\u003C!-- assets\u002Fcolors\u002Fcolors.xml -->\n\u003C?xml version=\"1.0\" encoding=\"utf-8\"?>\n\u003Cresources>\n  \u003Ccolor name=\"primary\">#FF6750A4\u003C\u002Fcolor>\n  \u003Ccolor name=\"surface_dim\">#FFDED8E1\u003C\u002Fcolor>\n\u003C\u002Fresources>\n```\n\n```dart\nimport 'package:myapp\u002Fgen\u002Fcolors.gen.dart';\n\nColoredBox(color: ColorName.primary);\n```\n\n> Nota: per un design system completo restano preferibili `ThemeExtension` e `ColorScheme`; `ColorName` è comodo come **sorgente** di valori grezzi da iniettare nel tema, non come sostituto del tema stesso.\n\n## Un caso d'uso concreto: precaching delle immagini\n\nUna delle funzioni meno note è la lista `values`, che raccoglie tutti gli asset di una cartella. Diventa banale fare il precache delle immagini critiche dello splash o dell'onboarding:\n\n```dart\nFuture\u003Cvoid> precacheOnboarding(BuildContext context) async {\n  await Future.wait([\n    for (final image in Assets.images.onboarding.values)\n      precacheImage(image.provider(), context),\n  ]);\n}\n```\n\nSe domani il designer aggiunge una quarta schermata di onboarding, il file viene incluso automaticamente: nessuna lista da aggiornare a mano.\n\n## Organizzare le cartelle per avere nomi leggibili\n\nI nomi generati derivano direttamente dal filesystem, quindi la struttura delle cartelle **è** la tua API. Qualche regola pratica:\n\n- usa `snake_case` per i file: `profile_placeholder.png` diventa `profilePlaceholder`, mentre `Profile Placeholder.png` genera nomi poco gradevoli (gli spazi vengono normalizzati, ma meglio evitarli);\n- non iniziare i nomi con un numero: `1_step.png` non è un identificatore Dart valido e viene prefissato automaticamente;\n- raggruppa per dominio, non per tipo: `assets\u002Fimages\u002Fonboarding\u002F`, `assets\u002Fimages\u002Fempty_states\u002F` sono più utili di una cartella `images` piatta con 80 file;\n- attenzione ai duplicati: `logo.png` e `logo.svg` nella stessa cartella generano collisioni di nome. Rinomina uno dei due (`logo_mark.svg`).\n\nSe preferisci nomi \"piatti\" puoi cambiare lo `style` in `snake-case` o `camel-case`: otterrai `Assets.imagesOnboardingStepOne` invece di `Assets.images.onboarding.stepOne`. Nella maggior parte dei casi `dot-delimiter` è più leggibile.\n\n## Monorepo e package condivisi\n\nSe gli asset vivono in un package separato (scenario comune con Melos), attiva:\n\n```yaml\nflutter_gen:\n  assets:\n    outputs:\n      package_parameter_enabled: true\n```\n\nIl codice generato includerà automaticamente il parametro `package:`, evitando il classico errore \"asset non trovato\" quando si carica una risorsa da un package diverso da quello dell'app host.\n\n## Generated code e controllo di versione\n\nLa domanda ricorrente: committare o no i file in `lib\u002Fgen\u002F`?\n\n**Committarli** è la scelta più pragmatica per i team piccoli: l'IDE funziona subito dopo il clone, le PR mostrano esplicitamente quando un asset viene aggiunto o rimosso e la CI non deve eseguire un passo extra prima dell'analisi statica.\n\nSe invece preferisci tenerli fuori dal repository, aggiungi a `.gitignore` la cartella di output e inserisci la generazione nella pipeline **prima** di `flutter analyze`:\n\n```yaml\n- run: flutter pub get\n- run: dart run build_runner build --delete-conflicting-outputs\n- run: flutter analyze\n- run: flutter test\n```\n\nIn entrambi i casi conviene escludere il codice generato dall'analisi statica e dal coverage:\n\n```yaml\n# analysis_options.yaml\nanalyzer:\n  exclude:\n    - lib\u002Fgen\u002F**\n    - \"**\u002F*.g.dart\"\n```\n\n## Cosa flutter_gen non fa\n\nÈ importante conoscere i limiti dello strumento:\n\n- **non ottimizza gli asset**: comprimere i PNG, convertire in WebP o ripulire gli SVG resta compito tuo (o di un passo di build dedicato);\n- **non verifica a runtime**: se cancelli un file e dimentichi di rigenerare, il codice compila ancora e fallisce a runtime. Per questo vale la pena aggiungere un check in CI che rigeneri e confronti il diff (`git diff --exit-code lib\u002Fgen\u002F`);\n- **non sostituisce la localizzazione**: per le stringhe servono `intl` o `slang`;\n- **non riduce il peso del bundle**: se un asset è dichiarato nel pubspec viene incluso, anche se nessuno lo referenzia. Un vantaggio indiretto però c'è: con i simboli generati è molto più facile cercare le referenze e capire quali immagini sono davvero inutilizzate prima di cancellarle.\n\n## Workflow consigliato\n\n1. Aggiungi l'asset nella cartella corretta con un nome in `snake_case`.\n2. Verifica che la cartella sia dichiarata in `flutter: assets:` (basta la directory, non il singolo file).\n3. Rigenera con `dart run build_runner build --delete-conflicting-outputs` — oppure tieni attivo `watch` durante lo sviluppo:\n\n```bash\ndart run build_runner watch --delete-conflicting-outputs\n```\n\n4. Usa il simbolo generato e vieta per convenzione (anche via code review) qualsiasi `Image.asset('...')` con stringa letterale.\n\nPer rendere la regola effettiva puoi persino aggiungere un lint custom con `custom_lint` che segnala l'uso di `Image.asset` con argomento letterale, ma nella pratica è sufficiente che il team adotti l'abitudine: una volta provato l'autocompletamento su `Assets.`, tornare indietro è difficile.\n\n## Conclusione\n\nflutter_gen è uno di quegli strumenti che costano cinque minuti di setup e restituiscono valore per tutta la vita del progetto. Trasforma risorse fragili — path, nomi di font, palette — in simboli Dart verificati dal compilatore, elimina un'intera categoria di bug a runtime e rende i refactoring degli asset un'operazione meccanica invece che un esercizio di archeologia tra le stringhe.\n","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002F99e4e551-c5fa-4959-bfb2-da6b30baf09a.jpg","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1699363238994-358966127d71?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w5NzA2NTJ8MHwxfHJhbmRvbXx8fHx8fHx8fDE3OTMwNzM2OTh8&ixlib=rb-4.1.0&q=80&w=1080",{"name":12,"author_url":13,"photo_url":14},"Ayush Kumar","https:\u002F\u002Funsplash.com\u002F@spexypants","https:\u002F\u002Funsplash.com\u002Fphotos\u002Fa-group-of-white-objects-sitting-on-top-of-a-table-LEMJHllZkZk",null,"published","2026-10-27T04:01:38+00:00","flutter_gen: asset type-safe in Flutter","Guida pratica a flutter_gen: genera classi Dart per immagini, SVG, font, Lottie e colori ed elimina le stringhe magiche dagli asset delle app Flutter.",{"id":21,"name":22,"slug":23},1,"Guide","guide",{"id":21,"name":25},"Flutter Bot",[],1793098101948]