11

EDIT: This question is about using AssetBundle, while that question (List of files in flutter) was about using Directory. They are different because of different classes. ALSO: I removed one section, that can be similar to previous question.

I don't understand how to use AssetBundle for accessing files...

For example, my assets in pubspec.yaml

assets:
- assets/images/
- assets/texts/
  1. AssetBundle has methods: loadString(key, ...) and loadStructuredData(key, ...) - what is a key and how to use this methods?

  2. I need to load data from text files and others files. I know that there is a rootBundle (or DefaultAssetBundle.of(context))... But how to use it to load files?!

Thanks!

Serge Breusov
  • 1,316
  • 4
  • 11
  • 24
  • Possible duplicate of [List of files in flutter](https://stackoverflow.com/questions/50975636/list-of-files-in-flutter) – Bostrot Jun 23 '18 at 09:53
  • 1
    @Bostrot Nope, they are different. Also, flutter is not java/c++/python or other mainstream topic where you can find many similar questions. So, in this case any point of difference is realy matter. – Serge Breusov Jun 23 '18 at 11:24
  • Thanks for this, I had forgotten that I had added an asset, and when testing, needed to add a test asset. This helped point me to the pubspec, and was able to quickly add the new asset, and get things working. – Hite Jul 27 '20 at 16:51

1 Answers1

15

Let's assume that you have an image clock.png in assets/images and a UTF-8 encoded text file distances.json in assets/texts.

The key is really just the path to the asset, so you might load the whole file as a String and decode the json like this:

String distancesText = await rootBundle.loadString('assets/texts/distances.json');
Map distances = json.decode(distancesText);

loadString takes care of the UTF-8 decode for you, and also caches the String for faster access next time.

loadStructuredData takes loadString one step further - it loads the String then calls your provided callback to parse the String and returns the result. This time it caches the decoded result - now saving the reading and decoding step the next time.

Map distances2 = await rootBundle
    .loadStructuredData('assets/texts/distances.json', (String s) async {
  return json.decode(s);
});

So, this is great for text files; what about binary files? You can read the whole asset as a byte array.

ByteData clockData = await rootBundle.load('assets/images/clock.png');
Uint8List clockBytes = clockData.buffer.asUint8List());

Now you can do whatever you need to do with the binary contents of the file. Note that unlike Strings, binary data isn't cached.

Of course, for a PNG, you would most likely not read it as bytes, but instead load it as an Image Widget with AssetImage. (Also asset images should have multiple resolutions for different DPI devices.) See Assets and Images.

I think that earlier you wanted to obtain a complete list of all the assets available. In some ways this makes no sense. You know which assets you provided at build time, so you could keep the list of assets somewhere yourself - in code or in your own manifest. If you really want to enumerate them at runtime, I think you can load an asset called AssetManifest.json, but this seems to be an implementation detail, so possibly subject to change.

Richard Heap
  • 48,344
  • 9
  • 130
  • 112
  • 1
    "In some ways this makes no sense." - I really don't undetsand this point of view... If you need 10-20 items, which are different by their nature (2 icons, 4 images, 1 setting and so on) - then I tottaly agree. But when all files are similar like list of epub-books, image gallery - your application don't depends on certain item, so your can freely add/remove/rename them during development and different versions. So, it is logical to get list of files in runtime. – Serge Breusov Jun 24 '18 at 19:12
  • "This time it caches the decoded result - now saving the reading and decoding step the next time." Next time = in other part of code? So, next time I use loadStructuredData IF the filename is cached THEN it will ignore the handle function and returned already cached result?! But If I want to use other parser (which give result in deffirent form) - it would be ignored and still return previously cached one? Still don't understand details.... – Serge Breusov Jun 24 '18 at 19:28
  • Getting the list a runtime: I still think the two proposed methods should work: parse `AssetManifest.json` or provide your own manifest created at build time. Caching of results: yes, if you execute code twice to fetch the same asset the second fetch should be faster as it's cached - and, yes, passing a different parser won't invalidate the cache so you will get the first result. If you want the ability to change the parser, use `load` (binary) or `loadString` (text) and parse each time (as in the first block of code, rather than the second). – Richard Heap Jun 24 '18 at 21:43
  • What is AssetManifest.json? You mean I need to write explicit command-ine script, which would be called during build and put list of files into AssetManifest.json, correct? Or... AssetManifest.json is special file in flutter?! – Serge Breusov Jun 24 '18 at 22:33
  • It's a special file that you could use, or provide your own. – Richard Heap Jun 24 '18 at 22:35
  • Em.... Are you sure?... Please, give me a link to doc... tried to google it, but I couldn't find any documentation about AssetManifest.json. I could find only links on github where file with same name used. And it looks strange. For example: {"assets/logo.png":["assets/logo.png"],"assets/login-screen-background.png":["assets/login-screen-background.png"],"assets/signup-screen-background.png":["assets/signup-screen-background.png"]} It looks like REMAPPING of filepathes, and it looks like useful/common practice, but not like Flutter system file. – Serge Breusov Jun 24 '18 at 23:05
  • As I said in the original answer, it seems to be an implementation detail, so subject to change, but seems to be just what you are looking for. – Richard Heap Jun 25 '18 at 06:58
  • Hey my image contains whitespace like "login screen background.png" and using this I get my path something like this "login%20screen%20background%20.png". How can I handle this. For more details see my issue https://stackoverflow.com/questions/62382350/unable-to-load-assets-images?noredirect=1# – Sachin Jun 15 '20 at 06:35