Reputation: 3550
I wrote a dart package which is being used by my flutter application. Inside the dart package I want to store some static data in a json file which I want to read from the dart package code.
However I can't find a way to access asset files directly from a dart package. Using the File(path).readAsString()
only works for dart console applications and using the rootBundle
only works for flutter packages/applications.
My question is: How can I access this file which is stored in the dart package assets directly from the pure dart package?
In a flutter package I would simply make the file available via pubspec.yml like this
flutter:
assets:
- lib/assets/b737.json
But I could not find a similar solution for a pure dart package.
Upvotes: 8
Views: 1862
Reputation: 3550
After long research and nice help from the community this feature simply doesn't seem to exist.
But there are workarounds:
Load the asset file from the flutter project via rootBundle.loadString() and specify the asset file in the flutter pubspec.yaml and pass the string data to the dart package. Check ch271828n's answer for details
An easy solution is to convert the pure dart package to a flutter package. Then it's not pure dart anymore, but that doesn't always hurt. Especially, when the package is used inside another flutter project/package.
Instead of providing asset files and reading the content at runtime, you can also directly safe the asset file content to a static const variable. For bigger assets however this might slow down your IDE if it indexes hundrets of thousands of lines from the assets. Excluding these files from the analyzer might help: analysis_options.dart
analyzer:
exclude:
- '**/assets/data/**'
You can also checkout the aspen package which assists with the previous solution. You specify the paths of the assets and via code generation the contents of these files are then saved to variables which are directly available from the code.
part 'assets.g.dart';
// @Asset is an annotation from package:aspen that marks the asset to be packed.
@Asset('asset:my_package/web/my-asset.txt')
// We create a const (it must be const!) value that holds the generated asset content.
const myTextAsset = TextAsset(text: _myTextAsset$content);
Upvotes: 2
Reputation: 89975
As an unintended alternative to the aspen
package, I wrote a resource_importer
package that also uses code generation to store data as literals. (I perhaps wouldn't have written it if I were aware of aspen
at the time. Alas.)
Usage is a bit different; assets are specified via pubspec.yaml
. For example:
resource_importer:
resources:
myImage: 'assets/image.png'
myLicense:
path: 'LICENSE'
type: String
Upvotes: 0
Reputation: 17587
It is "impossible" at the first look, because the Dart package can be used anywhere - e.g. used in a non-Flutter environment. Then there is really no way to find it.
However, there is a workaround: The inverse of control. Example code:
// pure dart package
abstract class AbstractAssetFileFetcherService {
String getAssetFileContent(String assetName);
}
AbstractAssetFileFetcherService? service;
void myFunctionThatUsesAssetFile() {
var myFirstFileContent = service.getAssetFileContent('my-first-file-name.png');
var mySecondFileContent = service.getAssetFileContent('my-second-file-name.json');
// ... use the file content happily ...
}
And in the Flutter package which you want to use the pure-dart package:
void main() {
service = AssetFileFetcherService(); // or use other IoC methods such as the `GetIt` Dart package
myFunctionThatUsesAssetFile();
}
class AssetFileFetcherService extends AbstractAssetFileFetcherService {
String getAssetFileContent(String assetName) {
return rootBundle.loadString(assetName); // just use any normal method. you are in Flutter environment here.
}
}
EDIT
Asset files of Flutter may not exist anywhere in the disk path - it can be compressed in the apk (android) file for example. In addition, you may not have sufficient permissions to do so.
https://flutter.dev/docs/development/ui/assets-and-images#asset-bundling
During a build, Flutter places assets into a special archive called the asset bundle that apps read from at runtime.
Upvotes: 3
Reputation: 305
Try this:
final stringData = await File('data.json').readAsString();
final data = json.decode(stringData);
Upvotes: 0
Reputation: 86
Acounding the documentation you should use the rootBundle to load your json:
String jsonString = await rootBundle.loadString('assets/b737.json');
If you are using it inside an Widget its recomended to user DefaultAssetBundle.of(context)
String jsonString = await DefaultAssetBundle
.of(context)
.loadString("assets/b737.json");
Upvotes: 0