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:
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.
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.
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.
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:
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
Organize assets: Create folders for
images
,icons
, andfonts
within theassets
folder (add more depending on what you need)Configure Fonts: Place your font files (e.g.,
Roboto-Regular.ttf
) in theassets/fonts/
folder.Configure Icons: Place your icon files (e.g.,
file_add.png
) in theassets/icons/
folder.Configure images: Place your image files (e.g.,
img.png
) in theassets/images/
folder.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
andfonts.gen.dart
files in thelib/gen/
folder.
Generated Files:
fonts.gen.dart
: This file contains the auto-generated font family class.class FontFamily { FontFamily._(); static const String roboto = 'Roboto'; }
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.dart
that 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