Loading AssetImages with Flutter
Asked Answered
C

3

8

I'm trying to define some assets for my Flutter app.

This is my directory structure:

- lib
- assets
 - images
   └ bg_login.png <-- this one is 400x800px
   └ 2.0x
     └ bg_login.png <-- this one is 800x1600px.
- test
- ios
- android
- build
- pubspec.yaml

This is my pubspec file (indented with 2 whitespaces):

name: my_app
description: My App

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

  assets:
    - assets/images/bg_login.png

I load the image like that:

new Positioned( 
  top: 0.0,
  width: MediaQuery.of(context).size.width,
  child: Image.asset(
    "assets/images/bg_login.png",
    fit: BoxFit.fitWidth,
  )
)

Sometimes the image loads, sometimes it fails with this error:

Launching lib\main.dart on Android SDK built for x86 in debug mode...
Initializing gradle...
Resolving dependencies...
Running 'gradlew assembleDebug'...
Built build\app\outputs\apk\debug\app-debug.apk.
Installing build\app\outputs\apk\app.apk...
Syncing files to device Android SDK built for x86...
D/        ( 3460): HostConnection::get() New Host Connection established 0xb099df40, tid 3479
D/EGL_emulation( 3460): eglMakeCurrent: 0xa325a620: ver 2 0 (tinfo 0xb0983620)
I/flutter ( 3460): ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════
I/flutter ( 3460): The following assertion was thrown resolving an image codec:
I/flutter ( 3460): Unable to load asset: assets/images/bg_login.png
I/flutter ( 3460): 
I/flutter ( 3460): When the exception was thrown, this was the stack:
I/flutter ( 3460): #0      PlatformAssetBundle.load (package:flutter/src/services/asset_bundle.dart:221:7)
I/flutter ( 3460): <asynchronous suspension>
I/flutter ( 3460): #1      AssetBundleImageProvider._loadAsync (package:flutter/src/painting/image_provider.dart:427:44)
I/flutter ( 3460): <asynchronous suspension>
I/flutter ( 3460): #2      AssetBundleImageProvider.load (package:flutter/src/painting/image_provider.dart:412:14)
I/flutter ( 3460): #3      ImageProvider.resolve.<anonymous closure>.<anonymous closure> (package:flutter/src/painting/image_provider.dart:266:86)
I/flutter ( 3460): #4      ImageCache.putIfAbsent (package:flutter/src/painting/image_cache.dart:143:20)
I/flutter ( 3460): #5      ImageProvider.resolve.<anonymous closure> (package:flutter/src/painting/image_provider.dart:266:63)
I/flutter ( 3460): (elided 8 frames from package dart:async)
I/flutter ( 3460): 
I/flutter ( 3460): Image provider: AssetImage(bundle: PlatformAssetBundle#267c3(), name: "assets/images/bg_login.png")
I/flutter ( 3460): Image key: AssetBundleImageKey(bundle: PlatformAssetBundle#267c3(), name: "assets/images/bg_login.png",
I/flutter ( 3460): scale: 1.0)
I/flutter ( 3460): ════════════════════════════════════════════════════════════════════════════════════════════════════

It really happens randomly, sometimes it works, most of the time it throws that error. I also tried with ImageAsset, I got the same error.

What's going on? Am I missing something on how to properly declare and load images?

Coss answered 1/10, 2018 at 14:21 Comment(5)
Does this problem appear if you left only one of images?Kabob
@AndreyTurkovsky Yes, it does. Actually I added the 2.0x directory because I thought flutter was failing to load the image due to its size. But even managing different sizes didn't help.Coss
But sometimes image loads. Haven't you found the pattern - what it depends from?Kabob
@AndreyTurkovsky I didn't. It literally happens randomly while hot-reloading. I can change a text, a component, anything really, sometimes it throws that error, sometimes it doesn't.Coss
What's this assets/img/ and assets/images/ discrepancy about between your explanation and the error message and the code?Forgery
G
2

Well, there is a slight difference between Image.asset and AssetImage.

Image.Asset is a Widget while AssetImage is an ImageProvider.

AssetImage is the image provider which fetches the data(image) from the assets bundle. While, Image.asset is a widget to render on the screen which also in backend uses AssetImage to load image from asset bundle.

For ex :

Container requires child widget so you can provide the Image.asset but, you cannot provide AssetImage child. Also, for DecorationImage requires image property so you can assign the AssetImage while you cannot assign the Image.asset widget.

You can also find which Widget requires child widget or ImageProvider while declaring the widgets in IDE's smart suggestions.

I hope this point is clear.

Geomorphology answered 4/10, 2019 at 12:25 Comment(0)
P
1

In your pubspec.yaml you can declare

flutter:
  assets:
    - assets/images

and still use your assets directory structure.

Flutter uses asset variants when choosing resolution appropriate images.

So it will assumes that you bg_login.png in the images folder will be at the normal scale and for different scale's type you can have a structure ike this:

.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.

where M and N are numeric identifiers that correspond to the nominal resolution of the images contained within, in other words, they specify the device pixel ratio that the images are intended for.

You can still call from the code Image.asset("assets/images/bg_login.png").
For reference Assets and image from Flutter.io

Purifoy answered 4/6, 2019 at 15:46 Comment(0)
L
0

create directory structure like this : https://i.sstatic.net/KChTo.png

and add pubspec.yaml

 assets:
- images/testImage.png
- images/2.0x/testImage.png
- images/3.0x/testImage.png

you can refer this link https://flutter.dev/docs/development/ui/assets-and-images

Laurin answered 4/6, 2019 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.