Assets in Flutter Apps
Assets are the files your app ships alongside its code: images, fonts, JSON files, animations, shaders. Flutter packs them into the app when it builds, and your Dart code reads them at runtime. Because they ship inside the app binary, they’re also one of the things a Shorebird patch can’t change, so it pays to know which of your files are assets.
Declaring and loading assets
Section titled “Declaring and loading assets”Flutter bundles only the files you list under flutter: assets: in
pubspec.yaml
(Adding assets and images):
A directory entry includes only the files directly inside it, not its
subdirectories; add each subdirectory as its own entry. Since Flutter 3.41, an
entry can also be limited to some platforms with path: and platforms:.
Load them by the same path:
Assets from a package dependency take its name:
AssetImage('icons/heart.png', package: 'my_icons'), or the path
packages/my_icons/icons/heart.png.
Resolution variants
Section titled “Resolution variants”For images, put higher-density versions in 2.0x/, 3.0x/ (and so on) folders
next to the main file, and declare only the main file. Flutter bundles the
variants and picks the closest one for the device’s pixel ratio: a device with a
ratio of 2.7 gets 3.0x/logo.png.
Fonts and icons
Section titled “Fonts and icons”Fonts are declared under flutter: fonts: and bundled the same way. Flutter
also tree shakes icon fonts in release builds: MaterialIcons-Regular.otf keeps
only the glyphs your Dart code uses. Using an icon you didn’t use before
therefore changes the font file in the build. --no-tree-shake-icons keeps
every glyph, at the cost of a larger app.
Shaders
Section titled “Shaders”Fragment shaders listed under flutter: shaders: are compiled when you build
and bundled with the assets, then loaded with FragmentProgram.fromAsset.
Where assets end up
Section titled “Where assets end up”At build time, Flutter places your assets in the app’s asset bundle:
- Android:
assets/flutter_assets/inside the APK or app bundle. - iOS and macOS:
flutter_assets/insideApp.framework. - Windows and Linux:
data/flutter_assets/next to the executable.
Each bundle also carries an AssetManifest listing what’s in it. Files that
belong to the native app rather than to Flutter, such as the launcher icon and
launch screen (android/app/src/main/res, ios/Runner/Assets.xcassets), are
built into Android resources or the iOS asset catalog instead. See
How Flutter builds your app
for the rest of the build output.
Assets and Code Push
Section titled “Assets and Code Push”A Shorebird patch replaces your compiled Dart code only. Every file above, from
flutter_assets to Android resources and the iOS asset catalog, stays as the
store release installed it. So:
- Adding or changing an asset needs a new store release. A patch that refers to an image the release doesn’t contain fails to load it on users’ devices.
- Removing an asset is safe if no code still uses it: the release keeps the file, and the patch just stops using it.
- Using a new icon from an icon font changes the tree-shaken font. The release’s font doesn’t have the glyph, so the icon renders incorrectly in the patched app.
shorebird patch compares the new build’s assets with the release’s and stops
to ask before publishing when assets were added or changed:
What each listed file means, and when it’s safe to continue, is covered in
Your app contains asset changes warning when creating a patch.
Keeping content changeable between releases
Section titled “Keeping content changeable between releases”Some content changes more often than your store releases. A few patterns keep it updatable:
- Put text and configuration in Dart code. Strings generated by Flutter’s
internationalization tooling
(
gen-l10n) compile into Dart code, so translation fixes can ship in a patch. So can constants and--dart-definevalues. - Draw simple graphics in code. A
CustomPainter, a gradient or a widget composition is Dart code; an SVG or PNG file is an asset. - Load content that changes often from the network, with
Image.networkor a caching package, instead of bundling it. The same applies to Lottie or Rive animations, which load from a URL as well as from an asset (see Flutter Animations). - Add assets in a release ahead of the code that uses them, when you know a feature is coming.
- Keep every icon glyph if your patches often start using new Material
icons.
--no-tree-shake-iconsis a Flutter flag, so pass it after--, to the release and to every patch:shorebird release android -- --no-tree-shake-icons.