I have fetched the details of the planet i.e. (NOM) No. of moons, Gravity and Density from an API.
And i have stored these details in an array PlanetInfo. And i want to display it using text widget like Text("${PlanetInfo[1]}", style: TextStyle(color: Colors.white)). but it is giving me an erro: RangeError (index): Invalid value: Valid value range is empty: 1
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:xperience/Models/planets.dart';
class PlanetDescNoMGD extends StatelessWidget {
final Planet planeteee;
List PlanetInfo = [];
getPlanetData() async {
var url =
"https://api.le-systeme-solaire.net/rest/bodies/${planeteee.planetApi}";
final uri = Uri.parse(url);
final response = await http.get(uri);
final body = response.body;
final jsondata = jsonDecode(body);
PlanetInfo.add(jsondata["moons"].length);
PlanetInfo.add(jsondata["gravity"]);
PlanetInfo.add(jsondata["density"]);
}
PlanetDescNoMGD({Key? key, required this.planeteee}) : super(key: key);
@override
void initState() {
this.getPlanetData();
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
"No. of moons",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.w700),
),
const SizedBox(
height: 12,
),
Text("${PlanetInfo[1]}", style: TextStyle(color: Colors.white))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
"Gravity",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
),
const SizedBox(
height: 12,
),
Text("${PlanetInfo[1]}" + " m/s²",
style: TextStyle(color: Colors.white))
//Text(${num} + " m/s²", style: TextStyle(color: Colors.white))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text(
"Density",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
),
const SizedBox(
height: 12,
),
Text("${PlanetInfo[2]}" + " g/cm3",
style: TextStyle(color: Colors.white))
],
),
],
);
}
}
I need a solution.
2
Answers
You do not know how to work with async functions. Please learn it.
You are making async request to API and directly trying to use respond from API. It is not possible. What is happening is your List PlanetInfo is empty when build is called. so you are getting error.
Stateless widgets does not have initState! I see you are trying to override initState that does not exist.
You need stateful widget to use setState.
Here is, with minimal change working version of your code. You need to use setState after data is loaded and change isLoaded = true.
Here is solution:
You have got 2 things to fix there.
Do not use PlanetInfo as a list of ints.
Make full use of defining a class: encapsulating data and improving readability.
Define the class as follows
Declare a member in state.
Now create an object in your fetch call and assign it to state member.
and display in widgets using attributes.
You can either use FutureBuilder to wait on building UI until api call is done, or do as @hiloliddin suggested (using isLoaded member and building ui based on its value).
In your current implementation you were getting the error because UI was built before api call finished and the list PlanetInfo was empty.