Flutter - "Range error (length)" when trying to parse local json data - json

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"
},
...

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,
);
}
},
)
}

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));
});
}

Related

Flutter Bind Json data in ListView not showing in UI

My Json response status code is 200 and the object is also created but when I try to bind it with UI in ListView it doesn't show anything. I have also parsed created the model from the json data.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = contactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
bool isSearching = false;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
_contactsModel = API_Manager().getContacts();
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = snapshot.data.contacts[index];
return Container(
height: 100,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(contact.owner.username,
style: TextStyle(fontSize: 16))
],
),
);
});
} else
return Center(child: CircularProgressIndicator());
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Example company',
style: TextStyle(fontSize: 16),
),
Text(
'Example company',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example',
style: TextStyle(fontSize: 16),
),
Text(
'example',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Output Screen:
ListView should be displayed here
Dart DevTools network analysis:
response code is displayed
Json Viewer:
Contacts Json
Json sample(complete json too big to upload here):
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
"core": {
"points": {
"id": "47",
"label": "Points"
},
"firstname": {
"id": "2",
"label": "First Name",
"value": "Jason"
},
"lastname": {
"id": "3",
"label": "Last Name",
"value": "Lamuda"
},
"...": {
"..." : "..."
}
},
"ipAddresses": [
{
"ip": "70.127.91.131",
"ipDetails": {
"city": "Bradenton",
"region": "Florida",
"timezone": "America/New_York",
}
},
"...": {
"..." : "..."
}
The JSON has this:
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
So your ContactModel.contacts is a Map keyed by the id values "897" etc, not a List, so this line returns null:
var contact = snapshot.data.contacts[index];
(This should throw an exception when you reference the members of contact.) You can index into the Map like this:
List keys = snapshot.data.contacts.keys.toList();
List values = snapshot.data.contacts.values.toList();
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = values[index];
BTW this line in API_Manager is strange:
contactsModel = contactsModel.fromJson(jsonMap);
It gives a Null pointer exception. It should of course be:
contactsModel = ContactsModel.fromJson(jsonMap);

ListView not displayed after update in Json Data

Status response code is 200 but the ListView is not displayed and stuck on the CircularProgressIndicator.
When I had 2 items in the Json data it was displaying just fine but as I added another item it doesn't show up!
I've tried removing ListView.separated and using ListView.builder instead and also tried using StreamBuilder but I don't seem to be using it correctly as I'm fairly new to Flutter. If I do have to use StreamBuilder can I be guided through how to use it properly here? Thank You.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = ContactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI Code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
_contactsModel = API_Manager().getContacts();
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (BuildContext context,
AsyncSnapshot<ContactsModel> snapshot) {
if (snapshot.hasData) {
return ListView.separated(
shrinkWrap: true,
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (BuildContext context, int index) {
List keys = snapshot.data.contacts.keys.toList();
List values =
snapshot.data.contacts.values.toList();
var contact = values[index];
return InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewContact()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
contact.owner.firstName +
" " +
contact.owner.lastName,
style: TextStyle(fontSize: 16),
),
Text(
contact.owner.username,
style: TextStyle(fontSize: 14),
),
SizedBox(
height: 5,
),
],
),
),
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 5,
);
},
);
} else
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueGrey[700],
valueColor: AlwaysStoppedAnimation<Color>(
Colors.cyan)));
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example company name',
style: TextStyle(fontSize: 16),
),
Text(
'example company domain',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example company name',
style: TextStyle(fontSize: 16),
),
Text(
'example company domain',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Json sample(complete json too big to upload here):
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
"core": {
"points": {
"id": "47",
"label": "Points"
},
"firstname": {
"id": "2",
"label": "First Name",
"value": "Jason"
},
"lastname": {
"id": "3",
"label": "Last Name",
"value": "Lamuda"
},
"...": {
"..." : "..."
}
},
"ipAddresses": [
{
"ip": "70.127.91.131",
"ipDetails": {
"city": "Bradenton",
"region": "Florida",
"timezone": "America/New_York",
}
},
"...": {
"..." : "..."
}
Output Screen(stuck on CircularProgressIndicator): here
create a function like
Future getContacts()async{
_contactsModel = API_Manager().getContacts();
}
then inside your initState
getContacts().then((value){
setState((){});
})

Displaying complex json in FormBuilderRadioGroup in flutter_form_builder flutter

I'm having trouble displaying 'option' and getting (print in terminal) the 'id' of the chosen option.
How can I retrieve the json as map and use it effectively in flutter_form_builder?
Here is the json object:
{
id: 7,
poll: What is the capital of Egypt?,
created_at: 2020-10-22 10:53:41,
votes_count: 4,
likes_count: 0,
options: [
{
id: 20,
option: Tunis,
pollId: 7,
votes_count: 1
}, {
id: 21,
option: Cairo,
pollId: 7,
votes_count: 3
}, {
id: 22,
option: New York,
pollId: 7,
votes_count: 0
}],
user_name: salem,
user_image: null,
topics: []
}
Here is my poll_details page:
import 'package:flutter/material.dart';
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:like_button/like_button.dart';
import '../services/poll_services.dart';
import '../widgets/loading_widget.dart';
class PollDetails extends StatefulWidget {
final id;
PollDetails({this.id});
#override
_PollDetailsState createState() => _PollDetailsState(id);
}
class _PollDetailsState extends State<PollDetails> {
var id;
_PollDetailsState(this.id);
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
#override
void initState() {
super.initState();
optionsList.clear();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(title: Text("Details")),
body: FutureBuilder(
future: singlePoll(id),
builder: (context, snapshot) {
if(snapshot.hasData){
return ListView(
padding: EdgeInsets.fromLTRB(18, 40, 18, 0),
children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
child: Container(
padding: EdgeInsets.fromLTRB(10, 40, 0, 40),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
color: Theme.of(context).primaryColor,
width: 5.0,
style: BorderStyle.solid
)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if(imgPath(snapshot.data) == null) CircleAvatar(radius: 35,child: Image.asset('images/avatar.png'))
else CircularProfileAvatar(
imgPath(snapshot.data),
radius: 35,
borderWidth: 3.0,
borderColor: Colors.white,
backgroundColor: Colors.transparent,
foregroundColor: Colors.transparent,
errorWidget: (context, url, error) => Container(child: Icon(Icons.error)),
placeHolder: (context, url) => Container(
width: 50,
height: 50,
child: Text("Loading image..."),
)
),
SizedBox(width: 10.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
userName(snapshot.data),
style: TextStyle(fontSize: 20)
),
Flexible(
fit: FlexFit.loose,
child: Text(
votesCount(snapshot.data).toString()+" participants to this poll",
style: TextStyle(fontSize: 13)
)
)
]
)
)
]
)
)
),
///////////////////////////////// POLLS //////////////////////////////////////////////
FormBuilder(
key: _fbKey,
autovalidateMode: AutovalidateMode.always,
child: FormBuilderRadioGroup(
attribute: 'options',
decoration: InputDecoration(labelText: 'Choose only one:'),
validators: [FormBuilderValidators.required()],
orientation: GroupedRadioOrientation.vertical,
options: [
for (var i in optionsList) i['option'].toString()
]
.map((option) => FormBuilderFieldOption(value: option))
.toList(growable: false),
)
),
RaisedButton(
child: Text("Submit"),
onPressed: () async{
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
// Loading().show(context);
var option = _fbKey.currentState.value['options'];
print(option);
// var resp = await createPoll(question, tagS, choiceS);
// if(resp['status'] == "success"){
// Navigator.pop(context); //pop dialog
// } else {
// Navigator.pop(context); //pop dialog
// }
}
}
),
//////////////////////////// Like Button ///////////////////////////////
Row(
children: [
LikeButton(
size: 40,
circleColor:
CircleColor(start: Colors.red, end: Colors.red),
bubblesColor: BubblesColor(
dotPrimaryColor: Colors.red,
dotSecondaryColor: Colors.red,
),
likeBuilder: (bool isLiked) {
return Icon(
Icons.favorite,
color: isLiked ? Colors.red : Colors.grey,
size: 40,
);
},
likeCount: likes(snapshot.data),
countBuilder: (int count, bool isLiked, String text) {
var color = isLiked ? Colors.red : Colors.grey;
Widget result;
if (count == 0) {
result = Text(
"0",
style: TextStyle(color: color),
);
} else
result = Text(
text,
style: TextStyle(color: color),
);
return result;
}
),
Expanded(child: Text(" have liked this. Show some love, too!"))
]
),
Column(
children: [
// optionsList.forEach((element) => Text('option'))
for (var i in optionsList) Text(i['option'].toString())
]
),
RaisedButton(
child: Text("data"),
onPressed: (){singlePoll(id);}
)
]
);
}else {
return Center(child: CircularProgressIndicator());
}
}
)
)
);
}
}
And here is the request I use to get the response:
Future singlePoll(int id) async {
String url = baseUrl+"poll/get";
var stringID = id.toString();
var token = await storage.read(key: "jwt");
try{
final response = await http.post(
url,
headers: {'Accept':'application/json', 'Authorization':token},
body: {'pollId':stringID}
);
var dataToJson = jsonDecode(response.body);
for (var option in dataToJson['options']){
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
print(dataToJson);
return dataToJson;
} catch (e){
print('error caught: $e');
}
}
As you can see, I used a work around to get the list and display it.
Any suggestion is valuable.
Thanks in advance...
You need to use setState() in here:
setState() {
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
You can read more from the official document and look at here.

"The method '[]' was called on null" in flutter app and the data is not getting displayed

I have been trying to display data on my flutter app by importing json file in my firebase account but i think there is some error in my code.
class MatchList{
List<MatchListItem> matchList;
MatchList({this.matchList});
factory MatchList.fromJSON(Map<dynamic,dynamic> json){
return MatchList(
matchList: parsematches(json)
);
}
static List<MatchListItem> parsematches(matchJSON){
var mList=matchJSON['browseMatches'] as List;
List<MatchListItem> matchList=mList.map((data) => MatchListItem.fromJson(data)).toList();
return matchList;
}
}
class MatchListItem {
int id;
String title;
String match;
String date;
String desc;
MatchListItem({this.id,this.title,this.match,this.date,this.desc});
factory MatchListItem.fromJson(Map<dynamic,dynamic> parsedJson) {
// print(parsedJson);
return MatchListItem(id: parsedJson['index'],title:parsedJson['title'],match: parsedJson['match'],date:parsedJson['date'],desc:parsedJson['desc']);
}
}
This is my matchListModel.dart file
import 'package:firebase_database/firebase_database.dart';
import 'package:nostra_prediction/matchListModel.dart';
import 'dart:async' show Future;
class MakeCall{
List<MatchListItem> listItems=[];
// ListItem recipeModelList=new ListItem();
Future<List<MatchListItem>> firebaseCalls (DatabaseReference databaseReference) async{
MatchList matchList;
DataSnapshot dataSnapshot = await databaseReference.once();
Map<dynamic,dynamic> jsonResponse=dataSnapshot.value[0]['content'];
matchList = new MatchList.fromJSON(jsonResponse);
print(matchList);
listItems.addAll(matchList.matchList);
// for(var i in matchList.matchList){
// listItems.addAll(matchList.matchList);
// }
// print(matchList.matchList[1].foodtitle);
print('Thatt ${listItems[0].title}');
// return matchList.matchList;
return listItems;
}
}
This is my getMainListInformation.dart file
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:nostra_prediction/constants.dart';
import 'package:nostra_prediction/getMainListInformation.dart';
class Matches extends StatefulWidget{
#override
MatchesList createState()=> MatchesList();
}
class MatchesList extends State<Matches>{
final color = const Color(0xffbfd6ba);
final colorText = const Color(0xffd1bad6);
final databaseReference = FirebaseDatabase.instance.reference();
final makecall= new MakeCall();
#override
Widget build(BuildContext context) {
var futureBuilder=new FutureBuilder(
future: makecall.firebaseCalls(databaseReference), // async work
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none: return new Text('Press button to start');
case ConnectionState.waiting: return new Text('Loading....');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return
ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index){
// return new Text(snapshot.data[index].foodtitle);
return Card(
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: SizedBox(
height: MediaQuery.of(context).size.height*0.15,
width: MediaQuery.of(context).size.width,
child: Card(
elevation: 0,
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 10,right: 5,top: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data[index].title, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20,fontFamily: 'Roboto-Black'),),
SizedBox(height:10.0),
Row(
children: <Widget>[
new IconTheme(
data: new IconThemeData(
color: Colors.black26),
child: new Icon(Icons.timer,size: 20.0,),
),
Text('${snapshot.data[index].match} minutes',style: TextStyle(fontWeight: FontWeight.w700,color: Colors.black26),)
],
)
],
)
],
),
),
// rightFavFood
],
),
)
],
)
)
),
),
);
},
);
}
},
);
return Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: color,
centerTitle: true,
// title: Text('Browsing', style: TextStyle(fontFamily: 'Roboto-Black',fontSize: 25,fontWeight: FontWeight.w500,color: Colors.black),),
title : new Image.asset('images/cooking.png'),
actions: <Widget>[
IconButton(icon: Icon(Icons.menu), color: Colors.black26,onPressed: (){print('Menu pressed');},)
],
elevation: 0.0,
),
body: new Column(
children: <Widget>[
new Container(
padding: EdgeInsets.only(top: 5.0,bottom: 10),
color: color,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonTheme(
minWidth: MediaQuery.of(context).size.width*0.4,
height: MediaQuery.of(context).size.height*0.06,
child:MaterialButton(
onPressed: (){
// MakeCall makecall= new MakeCall();
// var response=makecall.firebaseCalls(databaseReference);
// print(makecall.listItems[0].foodtitle);
// print(makecall.listItems[1].foodtitle);
// new ListView.builder(
// itemCount: makecall.listItems.length,
// itemBuilder: (BuildContext context, int index){
// return
// },
// );
},
color: Colors.white,
// disabledTextColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(left: Radius.circular(10.0), right: Radius.circular(1.0))
),
// elevation: 15.0,
splashColor: color,
highlightColor:color,
// highlightElevation: 1.0,
child: Text("Cook Book",style: TextStyle(fontFamily: 'Roboto-Thin ',color: Colors.black26,fontSize: 15),),
) ,
),
ButtonTheme(
minWidth: MediaQuery.of(context).size.width*0.4,
height: MediaQuery.of(context).size.height*0.06,
buttonColor: Colors.amberAccent,
child:MaterialButton(
onPressed: (){Scaffold.of(context).showSnackBar(SnackBar(content: Text('Hey There')));},
color: Colors.white,
// disabledTextColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(right: Radius.circular(10.0), left: Radius.circular(1.0))
),
// elevation: 15.0,
highlightColor:color,
// highlightElevation: 1.0,
child: Text("Favourite",style: TextStyle(fontFamily: 'Roboto-Thin ',color: Colors.black26,fontSize: 15)),
) ,
),
],
),
),
SizedBox(height: 0),
new Expanded(
//
child:Container(
child: futureBuilder,
) ,
//
),
],
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: color,
elevation: 20.0,
currentIndex: 0,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home,color: Colors.white,),
title: new Text('Home',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700)),
),
BottomNavigationBarItem(
icon: new Icon(Icons.add_circle,color: Colors.white,),
title: new Text('Add a Recipe',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700))
),
BottomNavigationBarItem(
icon: new Icon(Icons.collections,color: Colors.white,),
title: new Text('My recipes',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700),),
)
],
),
);
}
}
this is my body.dart file
{
"json": [{
"content": {
"browseMatches": [{
"index": 1,
"date" : "12/04/12",
"desc" : "asdfgh",
"match": "abcdefgh",
"title": "wxyz"
}, {
"index": 12,
"date" : "12/04/12",
"desc" : "qwerty",
"match": "abcd",
"title": "xyz"
}
]
}
}]
}
And lastly this is my json data.
I have been trying to display this json data in a listview on card but unable to do so.Please help!
the exact message which gets displayed is:
Error:NoSuchMethodFound.The method '[]' was called on null.
Receiver:null
Tried calling:

How to generate a list of cards based on the number of items in json file

I use the following code to generate 10 predefined cards on a flutter screen which doesn't change:
List cards = new List.generate(10, (i)=>new QuestionCard()).toList();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('My First App'),
backgroundColor:new Color(0xFF673AB7),
),
body: new Container(
child: new ListView(
children: cards,
)
)
);
}
}
class QuestionCard extends StatefulWidget {
#override
_QuestionCardState createState() => _QuestionCardState();
}
class _QuestionCardState extends State<QuestionCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Card(
borderOnForeground: true,
color: Colors.green,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
trailing: Icon(Icons.album),
title: Text('Q1'),
subtitle: Text('What is the name of this location?'),
),
new TextFormField(
decoration: new InputDecoration(
labelText: "Answer Question",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Type your answer here";
}else{
return null;
}
},
keyboardType: TextInputType.text,
style: new TextStyle(
fontFamily: "Poppins",
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('Save'),
onPressed: () {/* ... */},
),
],
),
],
),
),
);
}
}
My json is simple (questions.json):
{
"Questions":
[
{
"id" : 1,
"quest" : ["question one"]
},
{
"id" : 2,
"quest" : ["question two", "question three"]
},
{
"id" : 3,
"quest" : ["question four"]
},
{
"id" : 4,
"quest" : ["question five", "question six", "question seven"]
}
]
}
So I have 2 questions I need to solve:
1. If I have more than 1 question I'll need to add an additional text box for a response for which I'll use a different card type, 2, 3, 4 max, which I'll need to define once.
But my real question here:
How do I generate the list based on the json response:
Future _loadQuestionAssets() async
{
return await rootBundle.loadString('assets/questions.json');
}
Future loadQuestion() async{
String jsonString = await _loadQuestionAssets();
final jsonResponse = json.decode(jsonString);
Questions question = new Questions.fromJson(jsonResponse);
//List cards = new List.generate(length, generator)
}
try this:
class MyFirstApp extends StatefulWidget{
#override
createState()=> new _appState();
}
class _appState extends State<MyFirstApp>{
List _displayData;
//assuming that you saved your json file in your assets folder
loadJson() async {
String data = await rootBundle.loadString('assets/json/questions.json');
jsonResult = json.decode(data);
print(jsonResult);
setState((){
_displayData = jsonResult["Questions"];
});
}
#override
void initState(){
super.initState();
loadJson();
}
#override
Widget build(BuildContext context){
return Scaffold(
appbar: Appbar(
title: Text("My APP")
),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: _displayData == null ? Center(child: CircularProgressIndicator()) :
ListView.builder(
itemcount: _displayData.length,
itembuilder: (context, index){
return Container(
width: MediaQuery.of(context).size.width,
height: 80,
margin: EdgeInsets.only(bottom: 5),
child: Text(_displayData[index]["id"])
);
}
)
)
);
}
}