Assets/Resources
Flutter allows you to bundle assets (graphics, sounds, config files...) along with your flutter application however dart cli applications do not have this ability.
DCli provides a set of asset management tools and an api to work around this limitation.
DCli refers to assets as 'resources' to differentiate them from flutter assets.
If you use resources in a package that will be publish to pub.dev, remember there is a 10MB limit on the entire dart package.
DCli does this by packaging a resource into a .dart library and then providing an api that allows you to unpack the resources at runtime.
The dcli pack
command, base64 encodes each file and writes them as a multi-line string into a dart library under src/dcli/resource. The name of the dart library is randomly generated.
The pack command also creates a register of the packed libraries in src/dcli/resource/generated/resource_registry.g.dart.
DCli expects all resources to located within your dart project under:
You can also pack external resources by creating a pack.yaml file.
Packing resources
To pack your resources run:
The 'pack' command will scan the '<project root>/resource' directory and all subdirectories. Each file that it finds will be converted to a dart library under:
Each library name is generated using a md5 hash prefixed with the letter 'A' to make a valid class name. The library name is of the form A<md5hash>.g.dart
So the following resources:
Will result in to:
The contents of each resource is base64 encoded into a multi-line string. So the photo.png.dart file will something look like:
Resource Registry
As part of the packing process DCli also creates a registry of the packed resources. This is done by creating a dart library called:
<project root>/lib/src/dcli/resource/generated/resource_registry.g.dart
Each of the packed resources is listed in the register as a map with the 'mount point' as the key.
The mount point
is the path of the packed resource relative to the <project root>/resource
directory.
For external resources, you specify a mount point to the project's resource directory that must not collide with any actual resource names under the <project root>/resource directory.
The contents of the 'resource_registry.dart' are of the form.
Unpacking resources
DCli provides an API that allows your script to unpack its resources at run time.
The resources
field is a map and the key to the map is the original path to the packed file 'relative' to the resources directory.
e.g.
To unpack the resources on the target system use the ResourceRegistry
class.
The ResourceRegistory.resources
field is a map of the packed resources. The key is the path of the original resource file relative to the resource
directory.
Use the .unpack
method to unpack your resource to a local path on the target system.
The values in the resources map is a PackedResources
. The PackedResource
includes a checksum
field. The checksum can be used to see if the expanded resource is the same as the packed resource. You can use this to determine if you need to upgrade the unpacked resource with the latest packed one.
Unpack all resources
You can unpack all resources by interating over the resource values:
External Resources
You can also pack resources that are external to your project by creating a pack.yaml file under your project's tool/dcli directory.
The pack.yaml file allows you to specify a number of files and/or directories.
path
The path is an absolute path or path relative to your dart project's root directory.
This is normally used for resources that live outside the projects directory structure but can also specify a file/directory that lives within the project but outside the 'resource' folder.
The path can be a file or a directory.
If path is a directory then the directory is included recursively.
exclude
When the above path
key specifies a directory, you may want to selectively excludes some files under the specified directory.
To exclude paths under the path
key add an exclude section:
The list of excluded paths may be a path relative to the root of the path
directory or an absolute path.
An excluded path may be a file or a directory.
mount
When a file is packed an entry is added to the resource registry.
To unpack a file you need a key to the file in the registry.
The mount is the key into the resource registry.
For files under the <project root>/resource directory the mount is their relative path to the resource directory.
So for:
<project root>/resource/myfile.dart
The mount is myfile.dart
.
For files and directories specified in the pack.yaml you must specify a mount .
The mount is a virtual path and can be any path you wish provided that it does NOT collide with any other mount specified in pack.yaml or used by any file physically under the <project root>/resource directory.
A mount is always a relative path.
To unpack external resources you use the mount as the key into the ResourceRegistry.
Ignored files
By default the pack command ignores any hidden files (those beginning with a '.'). To include a hidden file or directory add an explit path statement to that file or directory.
Limits
If you plan on publishing your project to pub.dev be aware that pub.dev has a maximum package size of 10MB.
The base64 encoding process increases the file size by about 33%.
For apps that you deploy locally the limits are not documented but are probably constrained by your systems memory - so fairly large.
Automating packing of resources
If you use pub_release to publish to pub.dev then you can create a pre-release hook to have pub_release package your resources.
Last updated