Flutter Tried calling: [] error on list builder - flutter

I am showing list-builder i need to show just a static data right now I am just check itemCount right now later'll show data but it's showing error .
Here is my code
class _OrderPageState extends State<OrderPage> {
bool showCards = false;
var data;
#override
void initState() {
this.getOrders();
}
getOrders() async{
final storage = new FlutterSecureStorage();
String userId = await storage.read(key: "_userID");
String url =
'http://retailapi.airtechsolutions.pk/api/orders/customer/${userId}/0';
print(url);
http.Response res = await http.get(
url,
);
var data = json.decode(res.body.toString());
print(data);
if(data['description'].toString() == "Success"){
print(data['Orders']);
print(data['Orders'].length); //its printing 6 here
setState(() {
showCards = true;
});}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Order', style: Theme.of(context).textTheme.headline4),
),
body: showCards ? Container(
child: ListView.builder(
itemCount: data['Orders'].length,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 18.0, vertical: 20.0),
itemBuilder: (context, index) {
var order = orderList[index];
return SideInAnimation(index, child:GestureDetector(
onTap: () {
// Get.to(OrderDetailPage(order: order));
},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(12.0),
margin: EdgeInsets.only(bottom: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Theme.of(context).accentColor),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(order.id,
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Theme.of(context).primaryColor)),
SizedBox(height: 12.0),
Text(order.dateOrder, style: Theme.of(context).textTheme.subtitle2),
Divider(),
orderCardItem(context,
title: "order.orderstatus", data: order.orderStatus),
SizedBox(height: 12.0),
orderCardItem(context,
title: "order.items",
data: "${order.totalItem} " + tr("order.itemspurchased")),
SizedBox(height: 12.0),
priceItem(context,
title: "order.price", data: "\$ ${order.totalPrice}"),
],
),
),
));
},
),
) : Container(),
);
}
}
In my function its printing the length by in List builder its showing an error that Tried calling: ` But on the print where API load it's showing the length 6.

First you need to initalize a list or array then simply add your data into that variable and then call this variable to your listview builder
var ordersData = [];
then your getData() method should be like this
getOrders() async {
...
if (data['description'].toString() == "Success") {
ordersData.add(data['Orders']); // Add your data to array or list
print(ordersData.length); //its printing 6 here
}
...
}
Here your Listview like this
ListView.builder(
itemCount: ordersData.length, // Here you need to pass this lenght
...
)

Related

how to display updated value of a list in a gridTile

I have a class called Statics, which contains List variables that store number of values.
class Statics {
//24 is the maximum number of cells in gridView.
static List heatMaps = List.filled(24, "miner ID", growable: false);
static int selectedHeatMap = -1;
static List selectedMinerTemp = List.filled(24,0,growable: false);
static List isPressed = List.filled(24, false);
}
in another widget i have gridView to display the data from the lists of Statics,
the data stored in Statics changes every few seconds, when i press a tile and get the data it shows the updated data but it does not automatically update the data and you must click on the desired tile item (from the list of data) again.
here is my gridView:
GridView.count(
crossAxisCount: 3,
children: List.generate(
selectItemsNumber(selectedValue3), (index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
/////////////here////////////
Statics.selectedHeatMap = index;
Navigator.pushNamed(context, "/listOfMiners",
arguments: selectedValue2);
},
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
SizedBox(
height: 10,
),
Text(
Statics.heatMaps[index],
// widget.selectedMiner.toString(),
style: TextStyle(fontSize: 13),
),
Text(
Statics.selectedMinerTemp[index]
.toString(),
// widget.selectedMiner.toString(),
style: TextStyle(fontSize: 13),
),
],
),
),
width: 100,
height: 100,
color:Statics.isPressed[index] == false ? Colors.white : colorPicker(
Statics.selectedMinerTemp[index])),
),
);
}),
),
and this my method to catch the data:
Stream<GroupsStates?> streamItems() async* {
yield* Stream.periodic(Duration(seconds: 5), (_) async {
final client = ClientChannel(
LoginState.ipServerController.text,
port: 10000,
options: ChannelOptions(
credentials: ChannelCredentials.insecure(),
),
);
final stub = EngineClient(client);
try {
var result = (await stub.groupsStatesAll(Void()));
return result;
} catch (e) {
print('Cuaght error: $e');
} }).asyncMap((event) async => await event);
}

Flutter FutureBuilder calling function continuously

I have simple function which is calling data from firestore and filtering data. But issue is my futurebuilder keeps on loader situation (Data is called successfully i can see in console but now showing in future) I think its because my fucntion is calling in loop or something i have try to print something in my function which indicates me that my function is not stopping and thats why i think my futureBuilder keeps on loading.
My code
Future<List> getCustomerList() async {
print('calling');
String uUid1 = await storage.read(key: "uUid");
String uName1 = await storage.read(key: "uName");
String uNumber1 = await storage.read(key: "uNumber");
setState(() {
uUid = uUid1;
uName = uName1;
uNumber = uNumber1;
});
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Customers');
QuerySnapshot querySnapshot = await _collectionRef.get();
// Get data from docs and convert map to List
List allData = querySnapshot.docs
.where((element) => element['sellerUID'] == uUid)
.map((doc) => doc.data())
.toList();
double gGive = 0;
double gTake = 0;
double gCal = 0;
for (int i = 0; i < allData.length; i++) {
// print(allData[i]);
// print('give ${double.parse(allData[i]['give'].toString()) }');
// print('take ${double.parse(allData[i]['take'].toString()) }');
double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString()) >
0
? gGive += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString())
: gTake += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString());
}
// print(gGive);
// print(gTake);
setState(() {
Gtake = gGive.toString().replaceAll("-", "");
Ggive = gTake.toString().replaceAll("-", "");
});
if (greenBox) {
var check = allData.where((i) => i['take'] > i['give']).toList();
return check;
} else if (redBox) {
var check = allData.where((i) => i['give'] > 1).toList();
return check;
} else {
return allData;
}
}
And my futureBuilder look like this
Expanded(
child: Container(
height: Height * 0.5,
child: FutureBuilder(
future: getCustomerList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
list = snapshot.data;
return SingleChildScrollView(
child: Column(
children: [
Container(
height: Height * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder:
(BuildContext context,
int index) {
var showThis = list[index]
['give'] -
list[index]['take'];
return list[index]
['customerName']
.toString()
.contains(searchString)
? GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CustomerData(
data: list[
index])),
);
},
child: Padding(
padding:
const EdgeInsets
.only(
left: 13,
right: 13),
child: Container(
decoration:
BoxDecoration(
border: Border(
top: BorderSide(
color: Colors
.grey,
width:
.5)),
),
child: Padding(
padding:
const EdgeInsets
.all(
13.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
CircleAvatar(
child:
Text(
list[index]['customerName'][0]
.toString(),
style:
TextStyle(fontFamily: 'PoppinsBold'),
),
backgroundColor:
Color(0xffF7F9F9),
),
SizedBox(
width:
20,
),
Text(
list[index]['customerName']
.toString(),
style: TextStyle(
fontFamily:
'PoppinsMedium'),
),
],
),
Text(
'RS ${showThis.toString().replaceAll("-", "")}',
style: TextStyle(
fontFamily:
'PoppinsMedium',
color: list[index]['give'] - list[index]['take'] <
0
? Colors.green
: Colors.red),
),
],
),
),
),
),
)
: Container();
},
),
)
],
),
);
} else
return Center(
heightFactor: 1,
widthFactor: 1,
child: SizedBox(
height: 70,
width: 70,
child: CircularProgressIndicator(
strokeWidth: 2.5,
),
),
);
}),
),
),
I am damn sure its because futurebuilder keeps calling function which is returning data but because of keeps calling functions my Futurebuilder keeps showing loading.
You should not call setState inside the future that you are giving to the FutureBuilder.
The state actualization will cause the FutureBuilder to re-build. Meaning triggering the future again, and ... infinite loop !

pull to refresh in case 'No data' widget

I need help in this please i have a RefreshIndicator that loads a ListView when there is data in the database however I want to make the widget return Text widget 'no data' if the table empty instead of the ListView.
but the when the table is empty it error appear
_TypeError (type 'String' is not a subtype of type 'Iterable')
and that will appear in the refresh method i don't know what should i do i appreciate any help thanks in advance.
this the UI for the page
class _onlineResultTab extends State<onlineResultTab> {
List<ResultsModelClass> resultslist = new List();
List<CoursesModelClass> coursesist = new List();
ResultsModelClass resultsModelClass;
CoursesModelClass courseModelClass;
final GlobalKey<RefreshIndicatorState> refreshKey = GlobalKey<RefreshIndicatorState>();
DataApiProvider dataApiProvider = new DataApiProvider();
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
key: refreshKey,
onRefresh: refreshList,
child: _resultwidget(context),
),
);
}
fetchResultDetails() async {
final allRows = await DbHelper.mydb.getOnlineResultList();
allRows.forEach((row) => {
resultsModelClass = ResultsModelClass(
"",
row["Res_Stud_Index"],
row["Res_Stud_Name"],
row["Res_Sem"].toString(),
"",
"",
row["Res_Batch"],
row["Res_Courses"],
row["Res_Grade"],
row["Res_GPA"].toString(),
row["Res_CGPA"],
row["Res_Status"],
row["faculty_desc_e"],
row["major_desc_e"]),
resultslist.add(resultsModelClass)
});
if (this.mounted) {
setState(() {});
}
}
fetchCourse() async {
final allRows = await DbHelper.mydb.getResultcoursesList();
allRows.forEach((row) => {
courseModelClass = CoursesModelClass(
row["Res_Courses"],
row["Res_Grade"],
),
coursesist.add(courseModelClass)
});
if (this.mounted) {
setState(() {});
}
}
List<String> listHeader = ['Student Results Details'];
Widget _resultwidget(context) {
final _size = MediaQuery.of(context).size;
return resultslist.length == 0
? ListView.builder(
controller: ScrollController(),
itemCount: 1,
itemBuilder: (context, index) {
return Center(
child: Padding(
padding: EdgeInsets.only(top: _size.height * 0.4),
child: Text(
"No Result Details !",
style: TextStyle(fontSize: 20),
),
));
},
physics: AlwaysScrollableScrollPhysics(),
)
: new ListView.builder(
itemCount: listHeader.length,
itemBuilder: (context, index) {
//var _size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Center(
child: Padding(
padding: EdgeInsets.only(bottom: _size.height * 0.02),
child: Column(
children: [
Card(
elevation: 20,
margin: EdgeInsets.symmetric(
horizontal: _size.width * 0.005,
),
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor),
child: Center(
child: Text(
'Semester ' +
resultslist[0].Res_Sem +
' Result ',
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold),
),
),
),
),
],
))),
);
},
);
}
the refresh method
Future<String> refreshList() async {
refreshKey.currentState?.show(atTop: false);
//await Future.delayed(Duration(seconds: 10));
var studentIndex;
final allRows = await DbHelper.mydb.MainInfoCehck();
allRows.forEach((row) => {
row["Stud_Index"],
studentIndex = row["Stud_Index"].toString()
//print( row["Stud_Index"].toString())
});
print(studentIndex);
//void refreshResult(String studentIndex)async{
await dataApiProvider.refresh_result(studentIndex);
// }
if (this.mounted) {
setState(() {
coursesist.clear();
resultslist.clear();
fetchResultDetails();
fetchCourse();
});
}
return null;
}
Future<String> refresh_result(String studentIndex) async {
var url = main_urll + "?studentIndex=" + studentIndex.trim();
final response = await http.get(url);
List<ResultDetailsModel> ResulttDetailsListModel = [];
final resultInfo = jsonDecode(response.body)['result_info'];
DbHelper.mydb.deleteTableData("Result");
print('Result informations : ' + resultInfo.toString());
for (Map i in resultInfo) {
ResulttDetailsListModel.add(ResultDetailsModel.fromJson(i));
DbHelper.mydb.saveResultDetails(ResultDetailsModel.fromJson(i));
}
return "";
}
Please check if
resultslist == null or resultslist.isNotEmpty()
for Handling empty list

When I'm trying to remove items from the listview using provider it removed last element from the list in flutter

When I'm trying to remove item(like 0 index item) from this listview using provider it removed the last item from the list. while I'm deleting last element from the list successfully remove last item. I'm bit confusing why this kind of problem is happening to me.
Here I'm posting some code please check give your valuable suggestion. Also demonstrate on this video what issue is happening
Link:https://drive.google.com/file/d/1UYl8Z7vEj_tZCaYzqe0VqZL2iMla5nIZ/view?usp=sharing
Expected result: Whenever user press delete button then delete that particular row(item).
Delete method:- This is the delete method It'll be call when user press delete button from the list.
Future<void> acceptdeclinerequest(String requestStatus,int requestId) async{
String token = await CustomPreferences.getpreferences('token');
Map<String, String> requestHeaders;
if (token.isNotEmpty) {
requestHeaders = {
'Accept': 'application/json',
'Authorization': 'Bearer ' + token
};
} else {
requestHeaders = {
'Accept': 'application/json',
};
}
var reqdata = {
"request_id":requestId.toString(),
"status":requestStatus
};
print('accept request data is $reqdata');
try
{
final response =
await http.post(Connection.url + 'respond-place-request', headers: requestHeaders,body: reqdata);
if (response.statusCode == 200) {
Map<String, dynamic> responseJson = json.decode(response.body);
final existingProductIndex = _items.indexWhere((prod) => prod.id == requestId);
var existingProduct = _items[existingProductIndex];
_items.removeAt(existingProductIndex);
notifyListeners();
return responseJson;
} /*else if (response.statusCode == 500) {
return servererrorresponse;
}*/
} catch (exception) {
throw exception;
}
}
Main Widget class: This is the main widget class where I define Listview widget. I've used provider to get data from api which is written in modal class to populate in Listview and Listview child widgets is in seprate class which is RequestWidgets. In this class I've passed rowitems data to show in listview.
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
var connectionstatus;
var product;
var _isInit = true;
var _isLoading = false;
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
if (_isInit) {
setState(() {
_isLoading = true;
});
Provider.of<BandRequestModal>(context).getBandRequestList().then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
connectionstatus = Provider.of<ConnectivityResult>(context);
product = Provider.of<BandRequestModal>(context, listen: false);
// getRequestData();
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
key: _scaffoldKey,
appBar: CustomAppbar(
_scaffoldKey, Constants.requests, 100.0, filterRecord),
endDrawer: MenuDrawer(),
body:
/*(connectionstatus == ConnectivityResult.wifi ||
connectionstatus == ConnectivityResult.mobile)
? */
Consumer<BandRequestModal>(builder: (context, modal, child) {
return !_isLoading
? Container(child: LayoutBuilder(builder:
(BuildContext context, BoxConstraints constraints) {
return Container(
height: constraints.maxHeight,
child: modal.item.length > 0
? ListView.builder(
padding:
EdgeInsets.only(top: 10.0, bottom: 0.0),
itemCount: modal.item.length,
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, int i) {
return RequestWidgets(data: modal.item[i]);
})
: Center(
child: new Text(
Constants.norecordfound,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
),
// ],
// ),
);
}))
: Comman.loadingIndicator(Theme.of(context).primaryColor);
})
// : Comman.nointernetconnection(context)
// FutureBuilder<BandRequestModal>(
// future: Connection.bandRequestList(),
// builder: (context, snapshot) {
// switch (snapshot.connectionState)
// {
// case ConnectionState.none:
// break;
// case ConnectionState.waiting:
// return Comman.loadingIndicator(
// Theme.of(context).primaryColor);
// break;
// case ConnectionState.active:
// break;
// case ConnectionState.done:
// if (snapshot.hasError) {
// return Center(
// child: new Text(Constants.servererror),
// );
// }else if(snapshot.data==null){
// return Center(
// child: new Text(Constants.servererror),
// );
// } else if (snapshot.data.data.length == 0) {
// return Center(
// child: new Text(
// Constants.norecordfound,
// style: TextStyle(
// fontSize: 20.0, fontWeight: FontWeight.bold),
// ),
// );
// } else {
// return ListView.builder(
// padding:
// EdgeInsets.only(top: 10.0, bottom: 60.0),
// itemCount: snapshot.data.data.length,
// shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
// itemBuilder: (context, int i) {
// return RequestWidgets(data:snapshot.data.data[i]);
// });
// }
// break;
// }
// }):Comman.nointernetconnection(context)
));
}
Child widget class: This is the row items class of listview In this class we used many widgets to show place data.
class _RequestWidgetsState extends State<RequestWidgets> {
var getData;
var product;
#override
void initState() {
// TODO: implement initState
getData = widget.data;
super.initState();
}
#override
Widget build(BuildContext context) {
product = Provider.of<BandRequestModal>(context, listen: false);
return Container(
// alignment: Alignment.topLeft,
margin: EdgeInsets.only(top: 5.0),
child: ListTile(
// contentPadding: EdgeInsets.zero,
key: ObjectKey(getData),
leading: CircleAvatar(
radius: 30,
backgroundColor: Colors.transparent,
child: ClipOval(
child: (getData.placeDetails.image != null &&
getData.placeDetails.image != '')
? Image.network(
getData.placeDetails.image,
width: 90,
height: 90,
fit: BoxFit.cover,
)
: Image.asset(
Res.defaultImage,
width: 90,
height: 90,
fit: BoxFit.cover,
)),
),
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(getData.placeDetails.name,
style: TextStyle(
fontSize: 16.0,
fontFamily: 'Metropolis',
color: CustomColors.commentTitleColor))),
],
),
subtitle: Container(
margin: EdgeInsets.only(top: 1.0),
child: Column(children: <Widget>[
Container(
margin: EdgeInsets.only(top: 1.0),
child: Row(children: <Widget>[
Expanded(
child: Text(getData.placeDetails.address,
style: TextStyle(
fontSize: 15.0,
height: 1.2,
fontFamily: 'Metropolis',
color: CustomColors.commentSubtitleColor))),
]),
),
Container(
margin: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[],
)),
Divider(
color: CustomColors.commentlineColor,
thickness: 0.8,
)
])),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
child: CircleAvatar(
radius: 20,
backgroundColor: Colors.green,
child: Icon(
Icons.check,
color: Colors.white,
),
),
onTap: () {
acceptrejectpopup('1');
// {
// print('accept data $data');
// Comman.hideLoading(context);
// Comman.showSnakBar(data['message'],context);
// });
},
),
SizedBox(
width: 15.0,
),
GestureDetector(
child: CircleAvatar(
backgroundColor: Colors.red,
child: Icon(
Icons.clear,
color: Colors.white,
),
),
onTap: () {
// Comman.showLoading(context);
acceptrejectpopup('0');
/*product.acceptdeclinerequest('0',getData.id.toString()).then((data){
print('decline data $data');
Comman.hideLoading(context);
Comman.showSnakBar(data['message'],context);
});*/
},
)
],
),
),
);
}
//accept and reject
void acceptRejectRequest(String requestStatus) async {
try {
var response =
await product.acceptdeclinerequest(requestStatus, getData.id);
if (response['status'] == Constants.status_true) {
Comman.hideLoading(context);
Comman.showSnakBar(response['message'], context);
// setState(() {});
} else {
Comman.hideLoading(context);
}
} catch (exception) {
Comman.hideLoading(context);
Comman.showSnakBar(Constants.servererror, context);
}
}
//request accept/reject popup
Future<void> acceptrejectpopup(String reqStatus) {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Alert!',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
content: new Text(reqStatus == '1'
? Constants.reqAcceptmessage
: Constants.reqRejectemessage),
actions: <Widget>[
new FlatButton(
onPressed: () => Navigator.of(context).pop(),
child: new Text(Constants.notxt),
),
new FlatButton(
onPressed: () {
Navigator.of(context).pop();
Comman.showLoading(context);
acceptRejectRequest(reqStatus);
},
child: new Text(Constants.yestxt),
),
],
),
);
}
The provider is working just fine, the problem is when the provider notify the consumer the ListView updates the children, but the StatefulWidget check they're the same type (They're all RequestWidget) so they just update themselves (if you don't provide a key to the StatefulWidget they will try to check if they're the same element and update via the didChangeDependencies method), but you're updating the getData var in initState (which will call only once) so even if the consumer updates the value won't. Try it like this
#override
void initState() {
// TODO: implement initState
//getData = widget.data; not here
super.initState();
}
#override
void didChangeDependencies() {
// TODO: implement initState
getData = widget.data; //update it here
super.didChangeDependencies();
}
Other option would be just to give a specific key when building your widget in the itemBuilder so when the consumer updates it changes them accordingly
return RequestWidgets(key: ValueKey(modal.item[i].id),data: modal.item[i]);
// Or some value unique for each item
The problem here I guess is, in your Child widget class, since I can't see any requestId of the selected card being passed to the acceptdeclinerequest().
Your acceptdeclinerequest() expects two unique arguments to be passed when called:
String requestStatus
int requestId
If you look closely into the Child widget class, you are just passing requestStatus. I wonder from where are you getting this getData.id, and how is it identifying that some particular card is selected.
// look here, only requestStatus is being passed
onTap: () {
acceptrejectpopup('0');
}
// and here
onTap: () {
acceptrejectpopup('1');
}
And in your acceptRejectRequest, you are only passing requestStatus
acceptRejectRequest(reqStatus);
And then you call your acceptdeclinerequest() with this data
// machine is confused, where are we getting the getData.id
// it assumes the id as per it's need, hence the error
await product.acceptdeclinerequest(requestStatus, getData.id);
The machine is trying to figure out, which element you selected. Try to give the id from the selected card, and pass it to the method with correct getData.id of that particular element.
Suggestion: Pass in your id of the selected card when you are tapping on it, and then call your methods, and then pass it along to get the right requestId and remove it. Let your methods acceptrejectpopup() and acceptRejectRequest() accept the id of the selected item and then finally pass it to your acceptdeclinerequest()
// first step
onTap: () => acceptrejectpopup('0', your_card_reuqest_id);
// second step, pass data from the above popup method to acceptRejectRequest()
acceptRejectRequest(reqStatus, requestId);
//finally from acceptRejectRequest(reqStatus, requestId), pass it to the final method acceptdeclinerequest
acceptdeclinerequest(requestStatus, requestId);

How to display the JSON data fetched from API in flutter?

I want to fetch the data from API and display it in flutter app. I've been able to fetch the data and display it using ListView builder. But, the problem now I'm facing is that the scroll is not working properly in this case and I don't want to display the data in the form of Lists.
So, is there any other way where we can fetch the data and show it in the app. This is how the UI is going to look.
I'm unable to accomplish this using ListView builder or any other way as I'm very new to flutter.
This is my code which I used in another widget where I was facing the scrolling issue, to create the ListView:
#override
_AllEventsState createState() => _AllEventsState();
}
class _AllEventsState extends State<AllEvents> {
final String url =
"api-url";
List data;
#override
void initState() {
super.initState();
this.getAllEvents();
}
createRoute(id) {
print('args $id');
Navigator.pushNamed(context, '/eventdetail', arguments: id);
}
Future<String> getAllEvents() async {
var response = await http.get(
Uri.encodeFull(url),
headers: {"Accept": "application/json"},
);
setState(() {
var convertDataToJson = jsonDecode(response.body);
data = convertDataToJson["events"];
});
return "Success";
}
#override
Widget build(BuildContext context) {
ScrollController _controller = new ScrollController();
return Container(
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
controller: _controller,
shrinkWrap: true,
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext cont, int index) {
// format date
var dateString = data[index]["eventDate"];
var eventDate = Jiffy(dateString).MMMEd;
return Container(
padding: const EdgeInsets.fromLTRB(30, 7, 30, 7),
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new InkWell(
onTap: () {
print('card tapped');
createRoute(data[index]['_id']);
},
child: Card(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: hexToColor("#EBEBEB"),
),
borderRadius: BorderRadius.circular(8.0),
),
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
customText(
eventDate.toString(),
"#000000",
"20.0",
TextAlign.left,
"Roboto Black",
FontWeight.w900,
),
customText(
"10, 9",
"#000000",
"20.0",
TextAlign.right,
"Roboto Black",
FontWeight.w900,
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: customText(
"${data[index]['city']} | ${data[index]['arenaName']} | ${data[index]['categories'][0]['title']}",
"#000000",
"18.0",
TextAlign.left,
"Roboto Black",
FontWeight.w900,
),
),
],
),
],
),
),
),
),
],
),
),
);
},
),
);
}
}
This is how I'm fetching the data from the API in another widget:
print("$url${widget.eventId}");
var response = await http.get(
Uri.encodeFull("$url${widget.eventId}"),
// headers: {"Accept": "application/json"},
);
print('events response ${response.body}');
setState(() {
var convertDataToJson = jsonDecode(response.body);
data = convertDataToJson["event"];
print(data);
});
return "Success";
}```
Can you please suggest a way as to how I can display the data properly in flutter?
Use FutureBuilder to get data from api like this :-
FutureBuilder(
future: yourMethodName(),
builder: (context, AsyncSnapshot<NameOfModelClass> snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
}
// after getting data from api
},
);
Your method can be like this :
Future<NameOfModelClass> YourMethodName() async {
final response = await http.get('Your url here');
return NameOfModelClass.fromJson(json.decode(response.body.toString()));
}
The model class can be generate by using jsonToDart
I hope this help :)