Using Generated Assets in Flutter

Using Generated Assets in Flutter

Quick guide to using generated assets in Flutter

In a Flutter project, managing assets efficiently is crucial for a seamless development experience. Manually referencing assets can become cumbersome as your project scales. Here's where the flutter_gen package comes to the rescue, offering several advantages:

  1. Type Safety: One of the key benefits is type safety. With automatically generated assets, you get strongly-typed classes for each asset type (images, icons, fonts). This eliminates the risk of typos and makes it easier to discover available assets directly through code completion.

  2. Reduced Errors: Manually specifying asset paths can lead to errors, especially as the project grows. Automatic generation ensures accuracy, reducing the chance of runtime errors related to incorrect asset references.

  3. Code Maintainability: As your project evolves, maintaining and updating assets becomes more manageable. The generated asset classes act as a central reference point, making it easy to locate and modify assets without manually searching through the project.

  4. Enhanced Collaboration: When working in a team, automatically generated assets streamline collaboration. Team members can intuitively discover and use assets, reducing communication overhead related to asset paths.

Now, let's delve into the steps outlined for setting up a Flutter project with automatically generated assets:

Project Setup:

  1. Create a new Flutter project:

     flutter create flutter_auto_assets
     cd flutter_auto_assets
    

Add dependencies: Open the pubspec.yaml file and add the required dependencies.

name: flutter_auto_assets
description: A demo flutter app
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: '>=3.1.3 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  flutter_gen: ^5.3.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner:
  flutter_gen_runner:


flutter:
  uses-material-design: true
  assets:
    - assets/
    - assets/images/
    - assets/icons/

  fonts:
    - family: Roboto
      fonts:
        - asset: assets/fonts/Roboto-Regular.ttf
  1. Organize assets: Create folders for images, icons, and fonts within the assets folder (add more depending on what you need)

  2. Configure Fonts: Place your font files (e.g., Roboto-Regular.ttf) in the assets/fonts/ folder.

  3. Configure Icons: Place your icon files (e.g., file_add.png) in the assets/icons/ folder.

  4. Configure images: Place your image files (e.g., img.png) in the assets/images/ folder.

  5. Run Code Generation: Execute the following commands in the terminal.

     flutter pub get
     flutter pub run build_runner build
    

    This will generate assets.gen.dart and fonts.gen.dart files in the lib/gen/ folder.

Generated Files:

  1. fonts.gen.dart: This file contains the auto-generated font family class.

     class FontFamily {
       FontFamily._();
    
       static const String roboto = 'Roboto';
     }
    
  2. assets.gen.dart: This file contains the auto-generated classes for icons and images.

     /// GENERATED CODE - DO NOT MODIFY BY HAND
     /// *****************************************************
     ///  FlutterGen
     /// *****************************************************
    
     // coverage:ignore-file
     // ignore_for_file: type=lint
     // ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
    
     import 'package:flutter/widgets.dart';
    
     class $AssetsIconsGen {
       const $AssetsIconsGen();
    
       /// File path: assets/icons/file_add.png
       AssetGenImage get fileAdd => const AssetGenImage('assets/icons/file_add.png');
    
       /// List of all assets
       List<AssetGenImage> get values => [fileAdd];
     }
    
     class $AssetsImagesGen {
       const $AssetsImagesGen();
    
       /// File path: assets/images/img.png
       AssetGenImage get img => const AssetGenImage('assets/images/img.png');
    
       /// List of all assets
       List<AssetGenImage> get values => [img];
     }
    
     class Assets {
       Assets._();
    
       static const $AssetsIconsGen icons = $AssetsIconsGen();
       static const $AssetsImagesGen images = $AssetsImagesGen();
     }
    
     class AssetGenImage {
       const AssetGenImage(this._assetName);
    
       final String _assetName;
    
       Image image({
         Key? key,
         AssetBundle? bundle,
         ImageFrameBuilder? frameBuilder,
         ImageErrorWidgetBuilder? errorBuilder,
         String? semanticLabel,
         bool excludeFromSemantics = false,
         double? scale,
         double? width,
         double? height,
         Color? color,
         Animation<double>? opacity,
         BlendMode? colorBlendMode,
         BoxFit? fit,
         AlignmentGeometry alignment = Alignment.center,
         ImageRepeat repeat = ImageRepeat.noRepeat,
         Rect? centerSlice,
         bool matchTextDirection = false,
         bool gaplessPlayback = false,
         bool isAntiAlias = false,
         String? package,
         FilterQuality filterQuality = FilterQuality.low,
         int? cacheWidth,
         int? cacheHeight,
       }) {
         return Image.asset(
           _assetName,
           key: key,
           bundle: bundle,
           frameBuilder: frameBuilder,
           errorBuilder: errorBuilder,
           semanticLabel: semanticLabel,
           excludeFromSemantics: excludeFromSemantics,
           scale: scale,
           width: width,
           height: height,
           color: color,
           opacity: opacity,
           colorBlendMode: colorBlendMode,
           fit: fit,
           alignment: alignment,
           repeat: repeat,
           centerSlice: centerSlice,
           matchTextDirection: matchTextDirection,
           gaplessPlayback: gaplessPlayback,
           isAntiAlias: isAntiAlias,
           package: package,
           filterQuality: filterQuality,
           cacheWidth: cacheWidth,
           cacheHeight: cacheHeight,
         );
       }
    
       ImageProvider provider({
         AssetBundle? bundle,
         String? package,
       }) {
         return AssetImage(
           _assetName,
           bundle: bundle,
           package: package,
         );
       }
    
       String get path => _assetName;
    
       String get keyName => _assetName;
     }
    

Using Generated Assets in Code:

Now, let's write a simple code in main.dartthat utilizes these generated assets.

main.dart:

import 'gen/fonts.gen.dart';
import 'screens/entry_screen.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
      // using generated Font asset
      theme: ThemeData(fontFamily: FontFamily.roboto),
      debugShowCheckedModeBanner: false,
      home: const EntryScreen(),
    );
  }
}

Create a folder called screens inside the /lib folder and create a new file called entry_screen.dart and paste this code:

import 'package:flutter/material.dart';
import '../gen/assets.gen.dart';

class EntryScreen extends StatelessWidget {
  const EntryScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Image asset
            Image.asset(Assets.images.img.path),
            const SizedBox(height: 10),
            const Text(
              'Flutter Gen Assets',
              style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 18,
              ),
            ),
            const SizedBox(height: 10),

            // Icons asset
            Image.asset(Assets.icons.fileAdd.path),
          ],
        ),
      ),
    );
  }
}

Now you have a Flutter project set up to use automatically generated assets. The generated classes provide type-safe references to your assets, improving code readability and reducing errors. Remember to run flutter pub get and flutter pub run build_runner build whenever you add or modify assets.

To dive more into this use: https://pub.dev/packages/flutter_gen

Github Repo: https://github.com/Atuoha/flutter_auto_assets

Did you find this article valuable?

Support Flutter Aware by becoming a sponsor. Any amount is appreciated!