I have a use case where i have to load the asset image based on the value of the key logo_image
from a json file.
So i have this json with key logo_image
and value image1.png
:
{
"logo_image" : "image1.png"
}
There is an image inisde the assets folder like this: assets/image1.png
I have a class called GetAssets()
with a method called getAssetItems()
which loads the json file and another method called getLogo
which i will use as blueprint in the view to specify which key item i want to view:
class GetAssets {
Future<Map<String, dynamic>> getAssetItems() async {
String jsonData =
await rootBundle.loadString('assets/items.json');
Map<String, dynamic> data = jsonDecode(jsonData);
return data;
Future getLogo(String key) async {
var assets = await GetAssets().getAssetItems();
return 'assets/' assets[key];
}
}
I have a field called logo
and i have method called setAssets()
to load the logo and set the state of the logo with setState()
and i use initState()
to initialize setAssets()
. I have a Scaffold()
which i use to view the asset logo with the field logo
:
import 'package:flutter/material.dart';
class ShowLogo extends StatefulWidget {
const ShowLogo({Key? key}) : super(key: key);
@override
_ShowLogoState createState() => _ShowLogoState();
}
class _ShowLogoState extends State<ShowLogo> {
late String logo = "";
setAssets() async {
final logoFromAsset = await GetAssets().getLogo("logo_image");
setState(() {
logo = logoFromAsset;
});
}
@override
initState() {
setAssets();
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Image.asset(logo),);
}
}
I am able to show the logo on the screen of my phone, but i still get the error: Unable to load asset:
What is the cause of this? How can i resolve this issue?
CodePudding user response:
I think this is because of Json asset asynchronous method call.
When the widget executing then build(BuildContext context)
method try to build the widget immediately after the initState (setAssets)
method call.
For setAssets
method's asynchronous call, build(BuildContext context)
method already executed before setting logo = logoFromAsset
inside setAssets
method and the first time logo
variable remains with empty string which is not a valid asset path, thats why Image.asset(logo)
can not load the asset/image and throw an error.
But after few moment when your setAssets
asynchronous method call executed and called setState
this time the widget is rebuild with the non-empty/valid asset path and the logo is showing.
Try to set an default image/icon and I think this will resolve your issue.
import 'package:flutter/material.dart';
class ShowLogo extends StatefulWidget {
const ShowLogo({Key? key}) : super(key: key);
@override
_ShowLogoState createState() => _ShowLogoState();
}
class _ShowLogoState extends State<ShowLogo> {
late String logo = "";
setAssets() async {
final logoFromAsset = await GetAssets().getLogo("logo_image");
setState(() {
logo = logoFromAsset;
});
}
@override
initState() {
setAssets();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: logo != "" ? Image.asset(logo) : const Icon(Icons.image)
);
}
}