I have a app_bar_base.dart
file where i have an AppBar.
class AppBarBase extends StatelessWidget implements PreferredSizeWidget {
late double appBarHeight = LoadAppStyle().loadAppStyle();
AppBarBase({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppBar();
}
@override
Size get preferredSize => Size.fromHeight(appBarHeight);
}
I am calling the method LoadAppStyle().loadAppStyle()
from the file load_app_style
:
class LoadAppStyle {
loadAppStyle() async {
String jsonData =
await rootBundle.loadString('assets/config/app_style.json');
Map<String, dynamic> data = jsonDecode(jsonData);
var getHeight = double.parse(data["app_bar"]["app_bar_height"]);
return getHeight;
}
}
In the load_app_style.dart
file i grab the value of app_bar_heigt
from the app_style.json
in app_style.json
i have key app_bar_height
where i want to change the value manually to change the height of the App bar
{
"app_bar":
{
"app_bar_height": 78
},
}
But for some reason i get the error : type 'Future<dynamic>' is not a subtype of type 'double'
CodePudding user response:
You can add the type to your loadAppStyle
method. Since your method is async
it returns a Future.
Future<double> loadAppStyle() async {
...
return getHeight;
}
Now your error should be
type 'Future<double>' is not a subtype of type 'double'
Since your method returns a Future
you have to use await to get the value.
loadAppStyle() // Future<double>
await loadAppStyle() // double
If you want to use a value of a Future
inside a Widget, have a look at FutureBuilder.
For your case you could e.g. use the FutureBuilder
to retrieve the height and then pass it to AppBarBase
FutureBuilder<double>(
future: loadAppStyle(),
builder: (context, snapshot) {
if(snapshot.hasData) {
return AppBarBase(height: snapshot.data);
} else {
return const Center(child: CirclularProgressIndicator));
}
}
)
And change your AppBarBase
to the following.
class AppBarBase extends StatelessWidget implements PreferredSizeWidget {
AppBarBase({
Key? key,
required this.height,
}) : super(key: key);
final double height;
@override
Widget build(BuildContext context) {
return AppBar();
}
@override
Size get preferredSize => Size.fromHeight(height);
}
CodePudding user response:
In your example, loadAppStyle()
has no defined return type (dynamic) and it is marked as async (Future), hence the return type of this function is Future<dynamic>
. Size.fromHeight
function requires the double
value, hence you get this error - the expected type is double
, but Future<dynamic>
was found here.
To resolve the type differences, you should set the return type of a function:
class LoadAppStyle {
Future<double> loadAppStyle() async {
String jsonData =
await rootBundle.loadString('assets/config/app_style.json');
Map<String, dynamic> data = jsonDecode(jsonData);
var getHeight = double.parse(data["app_bar"]["app_bar_height"]);
return getHeight;
}
}
Now, since your function is async
, you must wait for your Future to finish and only then you could retrieve the double
value. It would look something like this:
class AppBarBase extends StatelessWidget implements PreferredSizeWidget {
late double appBarHeight = await LoadAppStyle().loadAppStyle(); // Throws error
AppBarBase({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppBar();
}
@override
Size get preferredSize => Size.fromHeight(appBarHeight);
}
However, this throws an error since you cannot use the asynchronous code when initialising a value this way. What could be a better way to do this is to wait for this value somewhere outside of your widget and pass the result via the constructor:
class AppBarBase extends StatelessWidget implements PreferredSizeWidget {
final double appBarHeight;
AppBarBase({
required this.appBarHeight,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AppBar();
}
@override
Size get preferredSize => Size.fromHeight(appBarHeight);
}
This way, you separate your UI code from the widget. Anyway, the way of keeping this UI-specific configuration inside the JSON file sounds way overengineered - consider just passing this value via constructor directly, like: AppBarBase(appBarHeight: 78)
.