No data from sever API's is not showing on Listview using flutter - flutter

I'm fetching data from server APIs, The data is being successfully fetched from the server but the issue is that when the data is provided to Listview it cant be shown. How can I show the data on Listview in a flutter/dart?
Following is the code for fetching data from server API's
List<String> jobTitles = [];
List officeNames = [ ];
List officeLocations = [ ];
List jobTypes = [ ];
Future getJobsData() async {
var response = await http
.get(Uri.https('hospitality92.com', 'api/jobsbycategory/All'));
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> jobData = map["jobs"];
if (jobTitles.length != 0) {
officeNames.clear();
jobTitles.clear();
officeLocations.clear();
jobTypes.clear();
}
for (var i = 0; i < jobData.length; i++) {
jobTitles.add(jobData[i]["title"]);
officeNames.add(jobData[i]["company_name"]);
officeLocations.add(jobData[i]["company_name"]);
jobTypes.add(jobData[i]["type"]);
}
/* print(jobTitles);
print(officeNames);
print(officeLocations);
print(jobTypes);*/
}
Here is the design code that I wanted to show:
Widget listCard(jobTitle, officeName, location, jobType, onPress) {
return Container(
child: InkWell(
onTap: onPress,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xC000000), Color(0xC000000)])),
child: ListTile(
leading: CircleAvatar(
radius: 30,
child: Image.asset(
"assets/ic_login.png",
height: 28,
width: 28,
),
),
title: Text(
jobTitle,
style: TextStyle(
fontSize: 16,
color: Colors.lightBlue,
fontFamily: 'Montserrat',
fontWeight: FontWeight.w500),
),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
children: [
Icon(
Icons.home_outlined,
color: Colors.black,
size: 16,
),
Text(
officeName,
style: TextStyle(fontSize: 10),
),
],
),
SizedBox(
width: 10,
),
Row(
children: [
Icon(
Icons.location_pin,
color: Colors.blueGrey,
size: 16,
),
SizedBox(
width: 2,
),
Text(
location,
style: TextStyle(fontSize: 10),
),
],
),
SizedBox(
width: 10,
),
Row(
children: [
Container(
margin: const EdgeInsets.fromLTRB(0, 4, 0, 0),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.lightBlueAccent,
Colors.lightBlueAccent
])),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
jobType,
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
),
],
)
//ElevatedButton(onPressed: () { }, child: Text("Full Time", style: TextStyle(fontSize: 10),),),
],
),
),
),
),
),
],
),
),
);
}
Here is the listview code
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: jobTitle.length,
itemBuilder: (context, index) {
return listCard(jobTitles[index], officeNames[index],
officeLocations[index], jobTypes[index], () {});
}),
If I provide the static data to list it will show on listview, but dynamic data is not being shown.

Try To below Code Your problem has been solved:
Create API Call Function
Future<List<dynamic>> getJobsData() async {
String url = 'https://hospitality92.com/api/jobsbycategory/All';
var response = await http.get(Uri.parse(url), headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
});
return json.decode(response.body)['jobs'];
}
Write/Create your Widget :
Center(
child: FutureBuilder<List<dynamic>>(
future: getJobsData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var title = snapshot.data[index]['title'];
var company = snapshot.data[index]['company_name'];
var skills = snapshot.data[index]['skills'];
var description = snapshot.data[index]['description'];
var positions = snapshot.data[index]['positions'];
return Card(
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.green.shade300,
),
borderRadius: BorderRadius.circular(15.0),
),
child: ListTile(
leading: Text(skills),
title: Text(title),
subtitle: Text(
company + '\n' + description,
),
trailing: Text(positions),
),
);
},
),
);
}
return CircularProgressIndicator();
},
),
),
Your Screen Look Like

Related

How do i return a container based on a list of item selected in flutter?

I have a list of items
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
And this list is directly responsible for my tab bar:
When i tap an item in the Tab bar i want to return a different container on each of them?
How do i go about this in flutter?
I tried returning an if statement just before the container but it seems i don't get the statement correctly.
this is the container i want to return if the item user select is All, and then put conditions in place for the rest items.
this is how i put the condition but it gives me this error
My return statement and code -
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
),
current = 1 ?? Text('hello')
FULL WIDGET ADDED
class NotificationsView extends StatefulWidget {
#override
State<NotificationsView> createState() => _NotificationsViewState();
}
class _NotificationsViewState extends State<NotificationsView> {
final controller = Get.put(NotificationsController());
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Notifications".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
centerTitle: false,
backgroundColor: Colors.transparent,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: RefreshIndicator(
onRefresh: () async {
},
child: ListView(
primary: true,
children: <Widget>[
filter(),
],
),
),
);
}
Widget notificationsList() {
return Obx(() {
if (!controller.notifications.isNotEmpty) {
return CircularLoadingWidget(
height: 300,
onCompleteText: "Notification List is Empty".tr,
);
} else {
var _notifications = controller.notifications;
return ListView.separated(
itemCount: _notifications.length,
separatorBuilder: (context, index) {
return SizedBox(height: 7);
},
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
var _notification = controller.notifications.elementAt(index);
if (_notification.data['message_id'] != null) {
return MessageNotificationItemWidget(
notification: _notification);
} else if (_notification.data['booking_id'] != null) {
return BookingNotificationItemWidget(
notification: _notification);
} else {
return NotificationItemWidget(
notification: _notification,
onDismissed: (notification) {
controller.removeNotification(notification);
},
onTap: (notification) async {
await controller.markAsReadNotification(notification);
},
);
}
});
}
});
}
Widget filter() {
return Container(
width: double.infinity,
margin: const EdgeInsets.all(5),
child: Column(
children: [
/// CUSTOM TABBAR
SizedBox(
width: double.infinity,
height: 60,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: items.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return Column(
children: [
GestureDetector(
onTap: () {
setState(() {
current = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: current == index
? Color(0xff34495E)
: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 5, bottom: 5),
child: Text(
items[index],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: current == index
? Colors.white
: Colors.grey),
),
),
),
),
),
],
);
}),
),
/// MAIN BODY
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0, bottom: 20),
child: Column(
children: [
Stack(
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffEFFAFF),
borderRadius:
BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset(
'assets/icon/suitcase.png'),
),
),
SizedBox(
width: 15,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'New Job started ',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
Text(
'Tailoring for John Cletus ',
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
Spacer(),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffFFE8E8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Urgent',
style: GoogleFonts.poppins(
color: Color(0xffC95E5E)),
),
),
),
],
),
],
),
Divider(
height: 5,
color: Color(0xffEFFAFF),
),
],
),
),
],
),
),
current = 1 ?? Text('hello')
],
),
);
}
}
You can use Builder if want to display different type of widget based on the current index.
Builder(
builder: (context) {
switch (current) {
case 0:
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
);
case 1:
return Text('Hello');
default:
return SizedBox.shrink();
}
},
);
Below approach will solve your problem. If you need further assistance, please feel free to comment.
int _currentIndex = 0;
var _containers = <Widget>[
AllContainer(),
JobsContainer(),
MessagesContainer(),
CustomerContainer(),
];
Widget _bottomTab() {
return BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onItemTapped, //
type: BottomNavigationBarType.fixed,
selectedLabelStyle: const TextStyle(color: Colors.blue),
selectedItemColor: WAPrimaryColor,
unselectedLabelStyle: const TextStyle(color: Colors.blue),
unselectedItemColor: Colors.grey,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(label: 'All'),
BottomNavigationBarItem(
label: 'Jobs'),
BottomNavigationBarItem(
label: 'Messages'),
BottomNavigationBarItem( label: 'Customer'),
],
);
}
void _onItemTapped(int index) async {
print('bottom index::: $index');
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: _bottomTab(),
body: Center(child: _containers.elementAt(_currentIndex)),
),
);
}
You can use conditional if on widget level,
like
/// MAIN BODY
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
...
),
if (current == 1) Text('hello')
Also can be use else if
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
) //you shouldnt put coma
else if (current == 1) Text('hello')
],
),
);
But creating a separate method will be better instead of putting it here
Widget getWidget(int index) {
/// MAIN BODY
if (current == 0) // or switch case
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
); //you shouldnt put coma
else if (current == 1) return Text('hello');
return Text("default");
}
And call the method getWidget(current).
Also there are some widget like PageView, IndexedStack will help to organize the code structure

How to extract specific value from object stored in cloud firestore and get the sum of those values according to needed filters?

I am having an issue in extracting specific value and querying with it. Please guide me on this.
Here is a data structure : (Using flutter/dart and cloudFirestore 3.1.18)
What I want to do is
extract the value of "amount" acccording to "isIncome" (boolean) from all the documents in "entries" collection and get the sum of those extracted amount.
to get the all the "amount" done in a day according to "entryLog" as well and show filtered data (according to date and income type) in listview builder as well.
This is the code I have return for getting all those entries in a stream
Stream<List<Entries>> streamAllEntries() {
var uid = FirebaseAuth.instance.currentUser.uid;
var stream = _db
.collection('entries')
.where("addedBy", isEqualTo: uid)
.orderBy('entryLog', descending: true)
.snapshots()
.map((event) =>
event.docs.map((e) => Entries.fromJson(e.data())).toList());
log(stream.toString());
return stream;
}
and this is my code for Showing DailyReports (here -- entries)
class DailyReports extends StatefulWidget {
const DailyReports({Key? key}) : super(key: key);
#override
State<DailyReports> createState() => _DailyReportsState();
}
class _DailyReportsState extends State<DailyReports> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: getBody(),
);
}
Widget getBody() {
var entries = Provider.of<List<Entries>>(context);
var size = MediaQuery.of(context).size;
return Container(
margin: const EdgeInsets.only(bottom: 5),
child: Column(
children: [
//header card
SizedBox(
height: 140,
child: Card(
child: Padding(
padding: const EdgeInsets.only(
top: 10, bottom: 10, right: 10, left: 10),
child:
//header row
Column(
children: [
//title
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Transactions",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 22),
),
Icon(Ionicons.search, color: ColorTheme().blackColor),
],
),
//day tabs
const SizedBox(height: 10),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: days.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
var day = days[index];
return weekTabs(size, index, day);
},
),
),
),
],
),
),
),
),
//income/expense card
incomeExpenseStatus(entries),
testbtn(),
// transaction summary
Expanded(child: transactionSection(entries)),
],
),
);
}
testbtn() {
return IconButton(
onPressed: () async {
await FirestoreService().addToAmountCollection(1000, true, "entry8");
},
icon: const Icon(Icons.mail, color: Colors.white));
}
Card incomeExpenseStatus(List<Entries> entries) {
return Card(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Transaction Summary",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Income",
style: TextStyle(),
),
const Text(
"Rs. 60000",
style: TextStyle(
color: Colors.green,
fontSize: 16,
fontWeight: FontWeight.bold),
),
Container(
width: 1,
height: 20,
color: Colors.black,
),
const Text(
"Expenses",
),
const Text(
"Rs. 100000",
style: TextStyle(
color: Colors.red,
fontSize: 16,
fontWeight: FontWeight.bold),
),
],
),
),
],
),
),
);
}
Widget transactionSection(List<Entries> entries) {
int? totalAmt;
return Card(
child: Column(
children: [
const SizedBox(height: 5),
Text(
"Transactions count : ${entries.length}",
style: const TextStyle(fontSize: 10, color: Colors.red),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 10),
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: entries.length,
itemBuilder: (context, index) {
var transaction = entries[index];
DateTime d = DateTime.parse(transaction.entryLog);
return Card(
child: ListTile(
//*?How icon color works
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => TransactionDetailScreen(
index: transaction)),
),
);
},
leading: CircleAvatar(
child: Center(
child: Icon(
getCategoryWiseIcon(
transaction.details!.category.toString()),
),
),
),
title: Text(transaction.details!.category.toString()),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(transaction.details!.remarks.toString()),
Text("$d"),
],
),
trailing: transaction.details!.isIncome == true
? Text("IN",
style:
TextStyle(color: ColorTheme().greenColor))
: Text("OUT",
style: TextStyle(
color: ColorTheme().primaryColor))),
);
}),
),
),
],
),
);
}
int activeDay = 1;
#override
void initState() {
activeDay = DateTimeExtractor().getDayAsInteger(activeDay);
super.initState();
}
Widget weekTabs(size, index, day) {
log('Active month:$activeDay');
return GestureDetector(
onTap: () {
setState(() {
activeDay = index;
});
},
child: Row(
children: [
Column(
children: [
Text(
day['label'],
style: TextStyle(
fontSize: 12,
color: activeDay == index
? ColorTheme().primaryColor
: ColorTheme().blackColor.withOpacity(0.8),
fontWeight: activeDay == index
? FontWeight.w500
: FontWeight.normal),
),
const SizedBox(height: 5),
Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: activeDay == index
? ColorTheme().primaryColor
: ColorTheme().whiteColor,
shape: BoxShape.circle,
border: Border.all(color: ColorTheme().primaryColor),
),
child: Center(
child: Text(
day['day'],
style: TextStyle(
fontSize: 12,
color: activeDay != index
? ColorTheme().primaryColor
: ColorTheme().whiteColor,
),
),
),
),
],
),
const SizedBox(width: 20),
],
),
);
}
}
This is my Entres model class
class Entries {
String? addedBy;
Details? details;
String? entryID;
dynamic entryLog;
String? gaadiID;
Entries({
this.addedBy = "",
this.details,
this.entryID = "",
this.entryLog,
this.gaadiID = "",
});
factory Entries.fromJson(Map<String, dynamic> json) =>
_$EntriesFromJson(json);
Map<String, dynamic> toJson() => _$EntriesToJson(this);
Entries _$EntriesFromJson(Map<String, dynamic> json) => Entries(
addedBy: json['addedBy'] as String? ?? "",
details: json['details'] == null
? null
: Details.fromJson(json['details'] as Map<String, dynamic>),
entryID: json['entryID'] as String? ?? "",
entryLog: json['entryLog'].toString(),
gaadiID: json['gaadiID'] as String? ?? "",
);
Map<String, dynamic> _$EntriesToJson(Entries instance) => <String, dynamic>{
'addedBy': instance.addedBy,
'details': instance.details,
'entryID': instance.entryID,
'entryLog': instance.entryLog.toString(),
'gaadiID': instance.gaadiID,
};
}
If you need any more info then please feel free to ask .

Flutter getX not updating UI after ading items to obs list

I'm using GetX to manage the state of my ecommerce app, and I'm stuck with the shopping cart.
I'm using Sqflite package to store carts locally.
issue: when i add a product to cart list it's not updating it automatically untill i restart the app i see the added items
Cart controller
addProductToCart(ProductModel product) async {
List<Map> items =
await _repository.getLocalByCondition('carts', 'productId', product.id);
if (items.length > 0) {
product.quantity = items.first['productQuantity'] + 1;
return await _repository.updateLocal(
'carts', 'productId', product.toMap());
}
product.quantity = 1;
return await _repository.saveLocal('carts', product.toMap());
}
#override
void onInit() {
super.onInit();
getCarts();
}
Add to cart product details
_addToCart(BuildContext context, ProductModel product) async {
int result = await _cartController.addProductToCart(product);
if (result > 0) {
Fluttertoast.showToast(msg: 'Item added to cart successfully!');
} else {
Fluttertoast.showToast(msg: 'Error to add product!');
}
}
Cart screen
Obx(() {
return Scaffold(
appBar: AppBar(
title: Text('Cart (${_cartController.cartList.length} items)',
style: TextStyle(color: Colors.black))),
bottomNavigationBar: InkWell(
onTap: () {
//_checkout(_cartController.cartList);
},
child: Container(
color: Colors.black,
height: 55,
margin: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Checkout',
style: TextStyle(color: Colors.white),
),
SizedBox(
width: 10,
),
Text(
'£' + _cartController.total.toString(),
style: TextStyle(color: Colors.white),
)
],
),
)),
body: _cartController.loading.isTrue
? Center(child: CircularProgressIndicator())
: _cartController.cartList.length > 0
? ListView.builder(
padding:
EdgeInsets.symmetric(horizontal: 8, vertical: 12),
itemBuilder: (context, index) {
return Dismissible(
key: Key(this
._cartController
.cartList[index]
.id
.toString()),
onDismissed: (val) async {
var x= await _cartController.deleteCartItem(
index, this._cartController.cartList[index].id);
if(x!>0) Fluttertoast.showToast(msg: 'deleted');
else{ Fluttertoast.showToast(msg: x.toString());
}
},
background: Container(
child: Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 28.0),
child: Icon(
Icons.delete_outline_outlined,
size: 36,
color: Colors.white,
),
)),
color: Colors.redAccent),
child: Card(
elevation: 5,
shape: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(7),
)),
child: Container(
margin: EdgeInsets.all(4),
height: 120,
child: Row(
children: [
Expanded(
flex: 3,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5),
topRight: Radius.circular(5)),
child: Image.network(
_cartController.cartList[index].photo,
width: 150,
height: 120,
fit: BoxFit.cover,
),
),
),
Expanded(
flex: 5,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
_cartController
.cartList[index].name,
overflow: TextOverflow.clip,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${_cartController.cartList[index].price - _cartController.cartList[index].discount} ' +
" x " +
_cartController
.cartList[index].quantity
.toString(),
style: TextStyle(
fontWeight: FontWeight.w500),
),
),
],
)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: Icon(Icons.keyboard_arrow_up),
onPressed: () {
_cartController.total.value += this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount;
this
._cartController
.cartList[index]
.quantity++;
},
),
Text(_cartController
.cartList[index].quantity
.toString()),
IconButton(
icon: Icon(Icons.keyboard_arrow_down),
onPressed: () {
if (_cartController
.cartList[index].quantity >
1) {
_cartController.total.value -= (this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount);
this
._cartController
.cartList[index]
.quantity--;
}
},
),
],
))
],
),
),
),
);
},
itemCount: _cartController.cartList.length,
)
: Center(
child: Text('Your Shopping cart is empty'),
));
});
You need to add product in _cartController.cartList.
_addToCart(BuildContext context, ProductModel product) async {
cartList.add(product);
....
}

ListView.builder returns Null check operator used on a null value

I'm developing a job search app that scrapes data from Indeed using Python which is being sent back to my Flutter UI as JSON data. The JSON data is being received successfully, however, Im getting an error of Null check operator used on a null value. The error appears to be stemming from the _jobSearch widget.
The relevant error-causing widget was ListView lib/ui/home_page.dart:256
Exception caught by scheduler library
Null check operator used on a null value
Here is the code:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter_job_portal/theme/colors.dart';
import 'package:flutter_job_portal/theme/images.dart';
import 'package:flutter_job_portal/ui/bottom_menu_bar.dart';
import 'package:flutter_job_portal/ui/job_detail_page.dart';
String job = ""; //user's response will be assigned to this variable
String final_response = "";
final _formkey = GlobalKey<FormState>(); //key created to interact with the form
//function to validate and save user form
Future<void> _savingData() async {
final validation = _formkey.currentState.validate();
if (!validation) {
return;
}
_formkey.currentState.save();
}
Future<List<Job>> _getJobs() async {
final url = 'http://127.0.0.1:5000/job';
final response1 = await http.post(Uri.parse(url), body: json.encode({'job': job}));
final response2 = await http.get(Uri.parse(url));
final decoded = json.decode(response2.body);
List<Job> jobs = [];
for (var i in decoded) {
Job job = Job(i['Title'], i['Company'], i['Location'], i['Salary']);
jobs.add(job);
}
return jobs;
}
class Job {
final String title;
final String company;
final String location;
final String salary;
Job(this.title, this.company, this.location, this.salary);
}
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
Widget _appBar(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(Images.user1),
),
Spacer(),
IconButton(
icon: Icon(Icons.notifications_none_rounded),
onPressed: () {},
)
],
),
);
}
Widget _header(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 12),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Hello, Alex!",
style: TextStyle(
fontSize: 15,
color: KColors.subtitle,
fontWeight: FontWeight.w500,
)),
SizedBox(
height: 6,
),
Text("Swipe to find your future",
style: TextStyle(
fontSize: 20,
color: KColors.title,
fontWeight: FontWeight.bold)),
SizedBox(
height: 10,
),
Row(
children: [
Expanded(
child: Container(
height: 45,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: KColors.lightGrey,
borderRadius: BorderRadius.circular(10)),
child: Form(
key: _formkey,
child: TextFormField(
decoration: InputDecoration(
hintText: 'Search job title or keywords',
),
onSaved: (value) {
job =
value; //getting data from the user form and assigning it to job
},
),
),
),
),
SizedBox(
width: 16,
),
Container(
decoration: BoxDecoration(
color: KColors.primary,
borderRadius: BorderRadius.circular(10),
),
height: 40,
child: IconButton(
color: KColors.primary,
icon: Icon(Icons.search, color: Colors.white),
onPressed: () async {
_savingData();
_getJobs();
},
),
)
],
)
],
),
);
}
Widget _recommendedSection(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
margin: EdgeInsets.symmetric(vertical: 12),
height: 200,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Recommended",
style: TextStyle(fontWeight: FontWeight.bold, color: KColors.title),
),
SizedBox(height: 10),
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: [
_recommendedJob(context,
company: "Google",
img: Images.google,
title: "UX Designer",
sub: "\$45,000 Remote",
isActive: true),
_recommendedJob(context,
company: "DropBox",
img: Images.dropbox,
title: "Research Assist",
sub: "\$45,000 Remote",
isActive: false)
],
),
),
],
),
);
}
Widget _recommendedJob(
BuildContext context, {
String img,
String company,
String title,
String sub,
bool isActive = false,
}) {
return Padding(
padding: const EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
Navigator.push(context, JobDetailPage.getJobDetail());
},
child: AspectRatio(
aspectRatio: 1.3,
child: Container(
decoration: BoxDecoration(
color: isActive ? KColors.primary : Colors.white,
borderRadius: BorderRadius.circular(7),
),
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 40,
width: 40,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: isActive ? Colors.white : KColors.lightGrey,
borderRadius: BorderRadius.circular(7),
),
child: Image.asset(img),
),
SizedBox(height: 16),
Text(
company,
style: TextStyle(
fontSize: 12,
color: isActive ? Colors.white38 : KColors.subtitle,
),
),
SizedBox(height: 6),
Text(
title,
style: TextStyle(
fontSize: 14,
color: isActive ? Colors.white : KColors.title,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 6),
Text(
sub,
style: TextStyle(
fontSize: 12,
color: isActive ? Colors.white38 : KColors.subtitle,
),
),
],
),
),
),
),
);
}
Widget _jobSearch(BuildContext context) {
return new Container(
child: FutureBuilder(
future: _getJobs(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading...'),
));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].location),
);
},
);
}
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: KColors.background,
bottomNavigationBar: BottomMenuBar(),
body: SafeArea(
child: Container(
width: MediaQuery.of(context).size.width,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_appBar(context),
_header(context),
_recommendedSection(context),
_jobSearch(context)
],
),
),
),
),
);
}
}

List.Builder giving range error in Flutter

I have added my entire code over here. The getRecords method takes more time to add to the lists and hence my list returns empty at first and so listbuilder fails giving range error and that only range accepted is 0. BTW, Its a Todo app.
InitState :
void initState() {
super.initState();
setState(() {
getRecords();
});
}
Getting from the database
void getRecordsAndDisplay() async {
final records = await Firestore.instance.collection('tasks').getDocuments();
for (var record in records.documents) {
if (record.data['phone'] == '1') {
int len = record.data['task'].length;
if (len != null || len != 0) {
for (int i = 0; i < len; i++) {
String temp = record.data['task'][i];
tasks.add(temp);
}
}
else
continue;
}
else
continue;
}
setState(() {
listView = ListView.builder(
scrollDirection: Axis.vertical,
itemCount: tasks.length,
itemBuilder: (BuildContext context,int index) {
return Container(
margin: EdgeInsets.only(bottom: 10.0),
decoration: BoxDecoration(
color: Colors.deepPurple[700],
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: ListTile(
onTap: (){},
leading: IconButton(
icon: Icon(Icons.delete),
iconSize: 25.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.removeAt(index);
checkValue.removeAt(index);
updateValue();
});
},
),
title: Text(
'${tasks[index]}',
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: checkValue[index]
? TextDecoration.lineThrough
: null,
),
),
trailing: Checkbox(
value: checkValue[index],
activeColor: Colors.white,
checkColor: Colors.deepPurple[700],
onChanged: (bool value) {
setState(() {
checkValue[index] = !checkValue[index];
});
},
),
),
);
},
);
});
}
Scaffold:
return Scaffold(
backgroundColor: Color(0xff8780FF),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
colors: [Colors.deepPurple[400], Color(0xff6B63FF)])),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(30.0, 30.0, 30.0, 15.0),
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
spreadRadius: 1.0,
blurRadius: 50.0,
),
]),
child: Icon(
Icons.list,
color: Colors.white,
size: 30.0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.only(
bottom: 20.0,
left: 30.0,
),
child: Text(
'Todo List',
style: TextStyle(
color: Colors.white,
fontSize: 35.0,
fontWeight: FontWeight.w900,
),
),
),
Expanded(
child: SizedBox(
width: 20.0,
),
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.add),
iconSize: 30.0,
color: Colors.white,
onPressed: () async {
final resultText = await showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen(),
isScrollControlled: true);
setState(() {
tasks.add(resultText);
checkValue.add(false);
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': FieldValue.arrayUnion([resultText]),
});
});
},
),
IconButton(
padding: EdgeInsets.only(
right: 10.0,
bottom: 20.0,
),
icon: Icon(Icons.delete_outline),
iconSize: 30.0,
color: Colors.white,
onPressed: () {
setState(() {
tasks.clear();
checkValue.clear();
Firestore.instance
.collection('tasks')
.document('1')
.updateData({
'task': null,
});
});
},
),
],
),
],
),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
height: MediaQuery.of(context).size.height,
child: listView,
),
),
],
),
),
),
);
Please help me out. I am stuck with this for a long time :(
the problem is that in initstate you cannot await for async methods so you should implement a StreamBuilder that wraps your listview..
A streambuilder is a widget that takes a stream and waits for the call completition then when the data is ok shows a widget -> your listview
A little example
StreamBuilder(
stream: YOUR_ASYNC_CALL_THAT_RETURN_A_STREAM,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
alignment: Alignment.center,
child: Text(
"NO ITEMS"
),
);
}
else {
var yourList = snapshot.data.documents;//there you have to do your implementation
return ListView.builder(
itemBuilder: (context, index) => buildItem(index,yourList[index]),
itemCount: yourList.length,
);
}
},
),