Flutterのアセットを楽に使う
従来のアセット管理
Flutterアプリの開発で、ローカルに保存した画像を表示することが多いです。
そのとき、以下のように実装するのは一般的だと思います。
# pubspec.yaml
flutter:
assets:
- assets/images/avatar.jpg
Widget build(BuildContext context) {
return Image.asset('assets/images/avatar.jpg');
}
しかし、この方法にはいくつかの問題点があります。
- タイプミスや存在しないリソースへの参照
- 開発効率や可読性の低下
リソースのパスを書き間違えたり、pubspec.yaml
の設定を忘れたりしたとしても、コンパイルエラーが発生しないので、バグったことを気づかないままリリースしてしまう可能性があります。
このリスクを解消するために、flutter_gen
というライブラリをご紹介したいと思います。
FlutterGenとは
flutter_genは、R.java
やR.swift
のような、画像、フォント、カラーなどのリソースへ安全にアクセスできるようにするためのコード自動生成ライブラリです[1]。
導入
- Homebrew(macOS and Linux)
$ brew install FlutterGen/tap/fluttergen
- Dart package(macOS, Linux and Windows)
$ dart pub global activate flutter_gen
- Flutter package
# pubspec.yaml
dev_dependencies:
build_runner:
flutter_gen_runner:
設定
デフォルトの設定値は以下になります。
# pubspec.yaml
# ...
flutter_gen:
# Optional
output: lib/gen/
# Optional
line_length: 80
# Optional
integrations:
flutter_svg: false
flare_flutter: false
rive: false
lottie: false
assets:
# Optional
enabled: true
# Optional
outputs:
# Optional
# Set to true if you want this package to be a package dependency
# See: https://flutter.dev/docs/development/ui/assets-and-images#from-packages
package_parameter_enabled: false
# Optional
# Available values:
# - camel-case
# - snake-case
# - dot-delimiter
style: dot-delimiter
class_name: Assets
# Ignore unwanted files
exclude: []
fonts:
# Optional
enabled: true
# Optional
outputs:
class_name: FontFamily
colors:
# Optional
enabled: true
# Optional
inputs: []
# Optional
outputs:
class_name: ColorName
pubspec.yaml
にflutter_gen
の設定を追加してカスタマイズできます。
例えば、SVG画像を表示したい場合は以下ように設定します。
# pubspec.yaml
# ...
flutter_gen:
integrations:
# flutter_svgを利用します
# https://pub.dev/packages/flutter_svg
flutter_svg: true
flutter:
# ...
assets:
- assets/images/avatar.svg
生成
- パッケージをインストール
$ flutter pub get
- コードを生成
$ flutter pub run build_runner build --delete-conflicting-outputs
使用
- 画像
Widget build(BuildContext context) {
return Assets.images.avatar.image(
width: 120,
height: 120,
fit: BoxFit.scaleDown,
);
}
Widget build(BuildContext context) {
// Same as Image.asset('assets/images/avatar.jpg')
return Image.asset(Assets.images.avatar.path);
}
Widget build(BuildContext context) {
// Use flutter_svg
return Assets.images.avatar.svg(
width: 120,
height: 120,
fit: BoxFit.scaleDown,
);
}
- フォント
flutter:
# ...
fonts:
- family: MyFont
fonts:
- asset: fonts/MyFont-Regular.ttf
- asset: fonts/MyFont-Bold.ttf
ThemeData(
fontFamily: FontFamily.myFont,
)
既知の問題
Bad state: No element
build_runner
を実行したらBad state: No element
というエラーが出て失敗します。
build.yaml
を作成してbuild_runner
の設定をカスタマイズすると発生します。
この場合、build.yaml
にpubspec.yaml
の依頼を追加すればエラーを解消できます。
targets:
$default:
sources:
include:
- pubspec.yaml # add this line
Bad state: Unable to generate package graph
pubspec.yaml
にgenerate: true
を設定していることが原因で、削除すればエラーを解消できます。
# pubspec.yaml
flutter:
generate: true <--- ⚠️Remove this line⚠️
Flutterの多言語対応を入れている場合、l10n.yaml
にsynthetic-package: false
を設定する必要もあります。
# l10n.yaml
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
synthetic-package: false <--- ⚠️Add this line⚠️
最後に
FlutterGenを導入することによって、画像などのアセットを安全かつ便利に管理できるようになりました。
これからもFlutter開発を楽しんでいきましょう。
Discussion