Reputation: 3563
I have a JSON file that has a text and each sentence is in a separate JSON object, the user shoud be able to navigate between sentenes with next()
and previous()
but when the app loads I get this error:
RangeError (index): Invalid value: Valid value range is empty: 0
until I press any other button on the screen that's when the text loads and get displayed.
The card itself is a statefulWidget and here's my code:
class _BottomCardsState extends State<BottomCards>{
bool isLoadingEnded = false;
Future<Null> getAllData() async{
await DefaultAssetBundle.of(context).loadString('assets/json/data.json').then((response){
isLoadingEnded = true;
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
});
}
@override
void initState() {
super.initState();
getAllData();
}
int dataIndex = 0;
@override
Widget build(BuildContext context) {
int myNbr = dataList[dataIndex].id;
return Container(
child: Material(
color: Colors.transparent,
child: Card(
margin: EdgeInsets.symmetric(horizontal: 10.0),
elevation: 6.0,
child: Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.symmetric(horizontal: 12.0,),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_left,),
onPressed: () {_previous();},
),
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_right,),
onPressed: () {_next();},
),
],
),
SizedBox(height: 4.0,),
isLoadingEnded == true ? Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: InkWell(
splashColor: Colors.lightBlue[100],
onTap: (){},
//the paragraph gets displayed here
child: Text(dataList[dataIndex].paragraph,
),
),
],
),
SizedBox(height: 8.0,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Chip(
backgroundColor: secondaryDark,
label: Text('Number: $myNbr',
style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w500),),
),
],
),
],
),
): Center(child: loadingIndicator(),),
SizedBox(height: 6.0),
],
),
),
),
),
);
}
}
` My JSON format:
{
"id": 1,
"paragraph": "lorem ipsum"
},
...
Upvotes: 0
Views: 558
Reputation: 1374
import 'package:flutter/services.dart' show rootBundle;
the first of fall your data is like a map, and you are trying to store in a list. as I can see your data is the type of map.
{
"id": 1,
"paragraph": "lorem ipsum"
}
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as Map;
Data data=Data.fromJson(parse);
}
and if JSON is contained list data then
[
{
"id": 1,
"paragraph": "lorem ipsum"
},
{
"id": 1,
"paragraph": "lorem ipsum"
}
]
then
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as List;
parse.forEach((d){
dataList.add(Data.fromJson(d));
});
}
Upvotes: 0
Reputation: 2117
You need to wait until data is filled up.
change your getAllData method. Like,
Future<List<Data>> getAllData() async{
var response = await DefaultAssetBundle.of(context).loadString('assets/json/data.json')
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
return dataList;
}
and now wait on build method. Like,
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Data>>(
future: getAllData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Here you can get data "+snapshot.data.toString());
//you can put your ui here
} else {
print("Waiting mode");
return Container(
color: Colors.blue,
);
}
},
)
}
Upvotes: 1