type 'bool' is not a subtype of type 'List<ternakModel> in a type cast - flutter

I have problem in the emulator android. type 'bool' is not a subtype of type 'List in a type cast. I can't solve of this. I use provider ListBuilder. so I'm retrieving data using the provider in the form of a list. Can you help?
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
TernakProvider ternakProvider = Provider.of<TernakProvider>(context);
return Consumer<TernakProvider>(
builder: (context, providerData, _) => FutureBuilder(
future: providerData.getTernak(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Text("Loading...");
}
List<ternakModel> ternak = snapshot.data as List<ternakModel>;
and this is file provider
class TernakProvider with ChangeNotifier {
List<ternakModel> _ternak = [];
List<ternakModel> get ternak => _ternak;
set ternak(List<ternakModel> ternak) {
_ternak = ternak;
notifyListeners();
}
Future<bool> getTernak() async {
try {
List<ternakModel> ternak = await TernakService().getTernak();
_ternak = ternak;
return true;
} catch (e) {
print(e);
return false;
}
}
}
and this is my service file
class TernakService {
String baseUrl = "BaseURL";
Future getTernak() async {
var url = Uri.parse("$baseUrl/api/ternak");
var response = await http.get(url);
print(response.body);
if (response.statusCode == 200) {
List data = jsonDecode(response.body)['data']['list'];
List<ternakModel> ternak = [];
for (var item in data) {
ternak.add(ternakModel.fromJson(item));
}
return ternak;
} else {
throw Exception('Gagal Get Ternak');
}
}
}
this is listview code
body: ListView.builder(
itemCount: ternak.length,
itemBuilder: (context, index) {
return Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const DetailTernak(),
settings: RouteSettings(
arguments:
ternak[index].id_ternak.toString(),
),
),
);
},
// width: MediaQuery.of(context).size.width / 0.5,
// margin: const EdgeInsets.only(left: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context)
.size
.width /
1.2,
margin: EdgeInsets.only(
left: 16,
right: 16,
top: 10,
bottom: 10),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
border: Border.all(
color: const Color(0xffE5E5E5),
width: 1,
),
boxShadow: [
BoxShadow(
blurStyle: BlurStyle.outer,
color: Colors.black
.withOpacity(0.1),
spreadRadius: 0,
blurRadius: 8,
offset: const Offset(0,
0), // changes position of shadow
),
],
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 15, top: 15),
child: Row(
children: [
Text(
"ID ",
style: regular
.copyWith(
color: Color(
0xFF646464),
),
),
Text(
"${ternak[index].id_ternak}",
style: semibold,
)
],
),
),
]),

Change your getTernak inside TernakProvider to this:
Future<List<ternakModel>> getTernak() async {
try {
List<ternakModel> ternak = await TernakService().getTernak();
_ternak = ternak;
return ternak;
} catch (e) {
print(e);
return [];
}
}

Related

Update State without reloading a widget in Flutter

I have a widget on a screen that receives its data from API calls. The API call is made inside the init method of the Navigation Bar so that continuous API calls can be prevented when going back and forth between screens. Although this works fine, I'm facing a real challenge in trying to get the state of the widget updated when new data is added to that particular API that the widget relies on for displaying data. I would therefore need to know how to display the updated data that I added to the Database by making a post request on a different screen. The only way this happens now is by way of reloading the entire app or by killing it. Any help will be appreciated.
This is the NavBar where the API is getting called. I usually make all the API calls at once here and something I have done here too.
NavBar
class CustomBottomNavigationState extends State<CustomBottomNavigation> {
bool isLoading = true;
int index = 2;
final screens = [
MenuScreen(),
LeaveScreen(),
// TaskList(),
HomeScreen(),
// PaySlipScreen(),
TaskList(),
Claimz_category(),
// ClaimzScreen()
];
#override
void initState() {
// TODO: implement initState
Provider.of<LeaveRequestViewModel>(context, listen: false)
.getLeaveRequest()
.then((value) {
Provider.of<AnnouncementViewModel>(context, listen: false)
.getAllAnouncements()
.then((value) {
Provider.of<TodaysTaskList>(context, listen: false)
.getTodaysTasks() //This is the API call in question
.then((value) {
setState(() {
isLoading = false;
});
});
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
final items = ['The icons are stored here'];
// TODO: implement build
return SafeArea(
child: Scaffold(
body: isLoading
? const Center(
child: CircularProgressIndicator(),
)
: screens[index],
extendBody: true,
bottomNavigationBar: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(200),
topRight: Radius.circular(200)),
boxShadow: [
BoxShadow(
color: Colors.transparent,
blurRadius: 10,
offset: Offset(1, 2))
]),
child: CurvedNavigationBar(
items: items,
index: index,
height: 60,
color: const Color.fromARGB(255, 70, 70, 70),
backgroundColor: Colors.transparent,
onTap: (index) => setState(() {
this.index = index;
})),
),
),
);
}
}
ToDoList widget(This the widget where the updates never reflect without reloading)
class ToDoListState extends State<ToDoList> {
#override
Widget build(BuildContext context) {
final toDoList = Provider.of<TodaysTaskList>(context).getToDoList; //This is the getter method that stores the data after it has been fetched from API
// TODO: implement build
return ContainerStyle(
height: SizeVariables.getHeight(context) * 0.35,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(
top: SizeVariables.getHeight(context) * 0.015,
left: SizeVariables.getWidth(context) * 0.04),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
// color: Colors.red,
child: FittedBox(
fit: BoxFit.contain,
child: Text(
'To do list',
style: Theme.of(context).textTheme.caption,
),
),
),
],
),
),
SizedBox(height: SizeVariables.getHeight(context) * 0.01),
Padding(
padding: EdgeInsets.only(
left: SizeVariables.getWidth(context) * 0.04,
top: SizeVariables.getHeight(context) * 0.005,
right: SizeVariables.getWidth(context) * 0.04),
child: SizedBox(
height: SizeVariables.getHeight(context) * 0.25,
child: Container(
// color: Colors.red,
child: toDoList['today'].isEmpty
? Center(
child: Lottie.asset('assets/json/ToDo.json'),
)
: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Row(
children: [
Icon(Icons.circle,
color: Colors.white,
size:
SizeVariables.getWidth(context) * 0.03),
SizedBox(
width:
SizeVariables.getWidth(context) * 0.02),
FittedBox(
fit: BoxFit.contain,
child: Text(
toDoList['today'][index]['task_name'], //This is where it is used
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodyText1),
)
],
),
separatorBuilder: (context, index) => Divider(
height: SizeVariables.getHeight(context) * 0.045,
color: Colors.white,
thickness: 0.5,
),
itemCount: toDoList['today'].length > 4
? 4
: toDoList['today'].length),
),
),
)
],
),
);
}
}
The other widget where the date gets added
class _TaskListState extends State<TaskList> {
#override
Widget build(BuildContext context) {
var floatingActionButton;
return Scaffold(
backgroundColor: Colors.black,
floatingActionButton: Container(
....
....,
child: FloatingActionButton(
backgroundColor: Color.fromARGB(255, 70, 69, 69),
onPressed: openDialog, //This is the method for posting data
child: Icon(Icons.add),
),
),
),
body: Container(
....
....
....
),
);
}
Future<dynamic> openDialog() => showDialog(
context: context,
builder: (context) => AlertDialog(
backgroundColor: Color.fromARGB(255, 87, 83, 83),
content: Form(
key: _key,
child: TextFormField(
controller: taskController,
maxLines: 5,
style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
border: InputBorder.none,
),
validator: (value) {
if (value!.isEmpty || value == '') {
return 'Please Enter Task';
} else {
input = value;
}
},
),
),
actions: [
InkWell(
onTap: () async {
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2010),
lastDate:
DateTime.now().add(const Duration(days: 365)))
.then((date) {
setState(() {
_dateTime = date;
});
print('Date Time: ${dateFormat.format(_dateTime!)}');
});
},
child: const Icon(Icons.calendar_month, color: Colors.white)),
TextButton(
child: Text(
"Add",
style: Theme.of(context).textTheme.bodyText1,
),
onPressed: () async {
Map<String, dynamic> _data = {
'task': taskController.text,
'task_date': dateFormat.format(_dateTime!).toString()
};
print(_data);
if (_key.currentState!.validate()) {
await Provider.of<ToDoViewModel>(context, listen: false)
.addToDo(_data, context) //This is the post method
.then((_) {
Navigator.of(context).pop();
Provider.of<TodaysTaskList>(context, listen: false)
.getTodaysTasks(); //I did this here again to re-initialize the data. I was under the impression that the new data would get initialized for the widget to reflect it on the other screen.
});
}
},
),
],
),
);
void add() {
Navigator.of(context).pop();
}
}
The Get API Call
class TodaysTaskList with ChangeNotifier {
Map<String, dynamic> _getToDoList = {};
Map<String, dynamic> get getToDoList {
return {..._getToDoList};
}
Future<void> getTodaysTasks() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
var response = await http.get(Uri.parse(AppUrl.toDoList), headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${localStorage.getString('token')}'
});
if (response.statusCode == 200) {
_getToDoList = json.decode(response.body);
} else {
_getToDoList = {};
}
print('TO DO LIST: $_getToDoList');
notifyListeners();
}
}
Please let me know for additional input.
i think it's because you didn't call the provider to update your state correctly
as i see that you declare new variable to store your provider like this
final toDoList = Provider.of<TodaysTaskList>(context).getToDoList;
then you use it like this
Text(
toDoList['today'][index]['task_name'], //This is where it is used
overflow: TextOverflow.ellipsis,
style: Theme.of(context)
.textTheme
.bodyText1),
)
it's not updating the state, you should wrap the widget that need to be updated with Consumer
Consumer<TodaysTaskList>(
builder: (context, data, child) {
return _Text(
data.[your_list]['today'][index]['task_name'],
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyText1),
);
},
);

How to display the saved state of a button when the page opens?

I have three buttons. The maximum that I can select (activate) is only one button. When switching buttons, I have activated should be true, and not activated - false. I write these values ​​to SharedPreferences for each button, store true or false. When I open the pages all the buttons are gray out (they are not selected). I need to save the button state that it was selected and display it when the page is opened. For example, I just need if the variable isVoltageAC = true, then the AC button will immediately turn purple when the page is opened. How to do it?
enum VoltageMode {
ac,
dc,
all,
}
class FilterDialog extends StatefulWidget {
const FilterDialog({
Key? key,
}) : super(key: key);
#override
State<FilterDialog> createState() => _FilterDialogState();
}
class _FilterDialogState extends State<FilterDialog> {
VoltageMode? selectedMode;
#override
Widget build(BuildContext context) {
return BlocBuilder<MapPreferencesCubit, MapPreferencesState>(
builder: (context, statePreferences) {
final MapPreferencesCubit mapPreferencesCubit =
BlocProvider.of<MapPreferencesCubit>(context);
if (statePreferences is MapPreferencesInitial) {
mapPreferencesCubit.getPreferences();
}
if (statePreferences is MapPreferencesLoaded) {
return BlocBuilder<MapfilterCubit, MapFilterState>(
builder: (context, stateFilter) {
final MapfilterCubit mapFilterCubit =
BlocProvider.of<MapfilterCubit>(context);
if (stateFilter is MapFilterInitial) {
mapFilterCubit.getFilter();
}
if (stateFilter is MapFilterLoaded) {
bool isVoltageAC = stateFilter.mapFilter.voltagePowerAC;
bool isVoltageDC = stateFilter.mapFilter.voltagePowerDC;
bool isVoltageAll = stateFilter.mapFilter.voltagePowerAll;
return SingleChildScrollView(
child: Dialog(
insetPadding: const EdgeInsets.only(
top: 121, left: 24, right: 24, bottom: 60),
child: Container(
decoration: const BoxDecoration(
color: constants.Colors.greyDark,
borderRadius: BorderRadius.all(Radius.circular(24)),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 26, 0, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [,
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 21),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.ac;
}),
child: _buttonVoltage(
'AC', selectedMode == VoltageMode.ac),
),
const SizedBox(width: 16),
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.dc
}),
child: _buttonVoltage(
'DC', selectedMode == VoltageMode.dc),
),
const SizedBox(width: 16),
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.all;
}),
child: _buttonVoltage(
'All', selectedMode == VoltageMode.all),
),
],
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 21),
child: DefaultButtonGlow(
text: 'Done',
onPressed: () {
Navigator.pop(context);;
mapFilterCubit
.setFilter(
MapFilter(
voltagePowerAC:
selectedMode == VoltageMode.ac,
voltagePowerDC:
selectedMode == VoltageMode.dc,
voltagePowerAll:
selectedMode == VoltageMode.all,
),
)
},
),
Widget _buttonVoltage(String nameButton, bool isActive) => Container(
padding: const EdgeInsets.symmetric(vertical: 11),
height: 40,
width: 87,
decoration: BoxDecoration(
color: isActive
? constants.Colors.purpleMain
: constants.Colors.white.withOpacity(0.15),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isActive ? Colors.transparent : constants.Colors.greyDark,
),
boxShadow: [
BoxShadow(
color: isActive
? constants.Colors.purpleMain.withOpacity(0.34)
: Colors.transparent,
blurRadius: 10,
spreadRadius: 2,
offset: const Offset(0.0, 1.0)),
],
),
alignment: Alignment.center,
child:
Text(nameButton, style: constants.Styles.smallBoldTextStyleWhite),
);
cubit
Future setFilter(MapFilter mapFilter) async {
await _repository.setFilter(mapFilter: mapFilter);
final MapFilter? filter = await _repository.getFilter();
emit(MapFilterLoaded(filter!));
return filter;}
sharedpreferences
Future setFilter({required MapFilter mapFilter}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(_filterName, jsonEncode(mapFilter.toJson()));
}
you can read this values from SharedPreferences in initState of page. In this way your default value is ready when page loaded.
then make everything after SingleChildScrollView in separate widget like this:
Widget _buildBody(){
return SingleChildScrollView(
child: Dialog(
...
),
);
}
and pass this widget in your bloc builder after all if statement by default.
then do this:
void initState() {
super.initState();
final SharedPreferences prefs = await SharedPreferences.getInstance();
var result = prefs.readData(_filterName);
if (result != null) {
MapFilter mapFilter = jsonDecode(mapFilter.fromJson(result));
if (mapFilter.voltagePowerAC){
selectedMode = VoltageMode.ac;
}else if (mapFilter.voltagePowerDC){
selectedMode = VoltageMode.dc;
} else {
selectedMode = VoltageMode.all;
}
}
}

Having issue with my favorite button functionality in flutter

I am having an issue with my favorite button. I have connected it with real-time firebase and each time I press the favorite icon it changes the state in firebase either true or false. when I press the heart button it always shows me different output sometimes it becomes red or black without affecting the other and sometimes it changes the other ones too (red or black). I have tried a lot to solve this but I am unable to get a solution for it.
class Home_page extends StatefulWidget {
#override
State<Home_page> createState() => _Home_pageState();
}
class _Home_pageState extends State<Home_page> {
//late StreamSubscription _dailySpecialStream;
var clr = Colors.grey;
//var item;
final List<String> _listItem = [
'assets/audi3.png',
'assets/audi.png',
'assets/audi2.png',
'assets/audi.png',
'assets/audi2.png',
'assets/audi3.png',
];
var name;
var auth1 = FirebaseAuth.instance.currentUser;
Data? c;
late final Value;
List<Data> dataList = [];
List<dynamic> d = [];
List<dynamic> favList = [];
#override
void initState() {
print("object");
super.initState();
print(auth1);
_activateListener();
}
void _activateListener() {
final _database = FirebaseDatabase.instance.ref();
_database.child('user').get().then((snapshot) {
dataList.clear();
favList.clear();
print("hello");
Value = snapshot.value as Map;
final datas = snapshot.children.forEach((element) {
d.add(element.key);
});
for (var k in d) {
//print("");
print(Value[k]['imgUrl']);
print((Value[k]['carName']).runtimeType);
dataList.add(Data(
Value[k]['carName'],
Value[k]['price'],
Value[k]["imgUrl"],
k,
));
if (auth1 != null) {
print(k);
print("auth1");
print(auth1);
DatabaseReference reference = FirebaseDatabase.instance
.ref()
.child("user")
.child(k)
.child("fav")
.child(auth1!.uid)
.child("state");
reference.get().then((s) {
print(s.value);
print("upp is vla");
if (s.value != null) {
if (s.value == true) {
// print(s.value);
// print("true");
favList.add(true);
print(favList);
} else {
//print(s.value);
print("false1");
favList.add(false);
//print(favList);
}
} else {
print("inelse");
favList.add(false);
print(favList);
}
});
}
}
Timer(Duration(seconds: 1), () {
setState(() {
inspect(favList);
});
});
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.white,
child: Stack(
children: [
Image.asset(
"assets/top.png",
fit: BoxFit.cover,
),
Column(
children: [
SizedBox(
height: 30,
),
search(context),
SizedBox(
height: 80,
),
Expanded(
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 40,
children: List.generate(
dataList.length, (index) => GridDesign(index)).toList(),
)),
],
)
],
),
),
),
);
}
SizedBox GridDesign(int index) {
return SizedBox(
child: Column(
children: [
Stack(
clipBehavior: Clip.none,
children: [
Container(
height: 15.h,
width: 45.w,
margin: EdgeInsets.only(left: 12, top: 12, right: 16),
decoration: BoxDecoration(
// border: Border.all(color: Colors.grey,style: BorderStyle.solid,width: 2),
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: NetworkImage(dataList[index].url.toString()),
fit: BoxFit.cover)),
),
Positioned(
bottom: -3,
right: 5,
child: Container(
height: 32,
width: 32,
child: Neumorphic(
padding: EdgeInsets.zero,
style: NeumorphicStyle(
//shape: NeumorphicShape.concave,
boxShape: NeumorphicBoxShape.roundRect(
BorderRadius.circular(50)),
color: Colors.white),
child: favList[index]
? IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (auth1 != null) {
print(auth1);
print("it's not null");
DatabaseReference favRef = FirebaseDatabase
.instance
.ref()
.child("user")
.child(
dataList[index].uploadId.toString())
.child("fav")
.child(auth1!.uid)
.child("state");
favRef.set(false);
setState(() {
favFun();
});
}
print("object");
},
icon: Icon(
Icons.favorite,
color: Colors.red,
),
)
: IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (auth1 != null) {
print("it's not null1");
print(auth1);
DatabaseReference favRef = FirebaseDatabase
.instance
.ref()
.child("user")
.child(
dataList[index].uploadId.toString())
.child("fav")
.child(auth1!.uid)
.child("state");
favRef.set(true);
setState(() {
favFun();
});
}
print("object");
},
icon: Icon(
Icons.favorite,
))),
),
),
],
),
SizedBox(
height: 4,
),
Expanded(child: Text(dataList[index].CarName.toString())),
SizedBox(height: 2),
Expanded(
child: Text("R" + dataList[index].price.toString()),
),
SizedBox(height: 3),
Expanded(
child: ElevatedButton(
onPressed: () =>
Get.to(DetailPage(dataList[index].Url, dataList[index].Price)),
child: Text("Details"),
style: ElevatedButton.styleFrom(primary: myColor),
))
],
),
);
}
void favFun() {
final _database = FirebaseDatabase.instance.ref();
_database.child('user').get().then((snapshot) {
favList.clear();
for (var k in d) {
//print("");
if (auth1 != null) {
print(k);
print("auth1");
print(auth1);
DatabaseReference reference = FirebaseDatabase.instance
.ref()
.child("user")
.child(k)
.child("fav")
.child(auth1!.uid)
.child("state");
reference.once().then((DatabaseEvent s) {
print(s.snapshot.value);
print("upp is vla");
if (s.snapshot.value != null) {
if (s.snapshot.value == true) {
// print(s.value);
// print("true");
favList.add(true);
print(favList);
} else {
//print(s.value);
print("false1");
favList.add(false);
//print(favList);
}
} else {
print("inelse");
favList.add(false);
print(favList);
}
});
}
}
Timer(Duration(seconds: 1), () {
setState(() {
//inspect(favList);
});
});
});
}
}
Have a look at the picture to get a better view

Flutter BLocConsumer, problem with display data from states when it changes

Bloc version 8.0.1
In builder i display ListView.builder when data loaded, but i also need listener that show alert dialog, and to show it i change state, but after i change state when user click on button, blocbuilder see that state changed and change ListView.builder to other widget that says "error happend"
What can i do with it? Also i am new in bloc, may u give me detail answer about this problem.
this is my BlocConsumer
BlocConsumer<AddCheckListBloc, AddCheckListState>(
builder: (context, state) {
if (state is CheckListTemplateEmpty) {
return const Text("");
} else if (state is CheckListTemplateLoading) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is CheckListTemplateLoaded) {
return ListView.builder(
itemCount: state.loadedTemplates.length,
itemBuilder: (BuildContext context, int index) {
if (state.loadedTemplates[index].isPaid == "True") {
return InkWell(
onTap: () {},
child: Container(
decoration: BoxDecoration(border: Border.all(color: const Color.fromARGB(255, 141, 166, 255), width: 1), borderRadius: BorderRadius.circular(10), color: Colors.grey),
width: 50,
margin: const EdgeInsets.only(left: 20, right: 20, top: 14),
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
state.loadedTemplates[index].name,
style: const TextStyle(fontSize: 30),
),
Text(state.loadedTemplates[index].price.toString())
],
),
),
);
} else {
return InkWell(
onTap: () {
addCheckListBloc.add(ShowAlertDialogEvent(state.loadedTemplates[index]));
},
child: Container(
decoration: BoxDecoration(border: Border.all(color: const Color.fromARGB(255, 141, 166, 255), width: 1), borderRadius: BorderRadius.circular(10), color: Colors.white),
width: 50,
margin: const EdgeInsets.only(left: 20, right: 20, top: 14),
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
state.loadedTemplates[index].name,
style: const TextStyle(fontSize: 30),
)
],
),
),
);
}
});
} else {
return const Center(
child: Text("Ошибка, информацию недоступна к загрузке с сервера"),
);
}
},
listener: (context, state) {
{
if (state is OpenAlertDialogState) {
SchedulerBinding.instance!.addPostFrameCallback((_) {
showDialog(
context: context,
builder: (BuildContext context) {
String description = "";
return AlertDialog(
title: const Text("Добавить чеклист?"),
content: Container(
decoration: BoxDecoration(border: Border.all(color: const Color.fromARGB(255, 141, 166, 255), width: 1), borderRadius: BorderRadius.circular(10), color: Colors.white),
child: TextField(
decoration: const InputDecoration.collapsed(hintText: "Описание", border: InputBorder.none),
maxLines: null,
onChanged: (String value) async {
description = value;
},
),
),
actions: [
TextButton(
onPressed: () {
// Сделать что-то, чтобы закрыть диалог вместе с блоком
},
child: const Text("Нет"),
),
TextButton(
onPressed: () {
addCheckListBloc.add(AddNewCheckList(state.checkListTemplate, description));
},
child: const Text("Да"),
)
],
);
});
});
}
if (state is CloseAlertDialogState) {
SchedulerBinding.instance!.addPostFrameCallback((timeStamp) {
Navigator.pop(context);
});
}
;
}
},
);
this is my Bloc
class AddCheckListBloc extends Bloc<AddCheckListEvent, AddCheckListState> {
final CheckListRepository _checkListRepository;
AddCheckListBloc({required CheckListRepository checkListRepository})
: _checkListRepository = checkListRepository,
super(CheckListTemplateLoading()) {
on<OnCheckListTemplateLoad>((event, Emitter<AddCheckListState> emit) => _loadCheckListTemplates(event, emit));
on<AddNewCheckList>((event, emit) => _addNewCheckList(event, emit));
on<ShowAlertDialogEvent>((event, emit) => _showAlertDialog(event, emit));
}
Future<void> _loadCheckListTemplates(OnCheckListTemplateLoad event, Emitter emit) async {
emit(CheckListTemplateLoading());
try {
final List<CheckListTemplate> loadedTemplates = await _checkListRepository.getCheckListTemplateList();
emit(CheckListTemplateLoaded(loadedTemplates: loadedTemplates));
} catch (e) {
print(e.toString());
emit(CheckListTemplateError());
}
}
Future<void> _addNewCheckList(AddNewCheckList event, Emitter<AddCheckListState> emit) async {
emit(AddingNewCheckList());
try {
final template = event.checkListTemplate;
List<CheckListPoint> _checkListPointList = [];
for (int i = 0; i < template.checkListPointList!.length; i++) {
CheckListPoint _checkListPoint = CheckListPoint(false, false, template.checkListPointList![i].requirement, template.checkListPointList![i].notes, false, template.checkListPointList![i].requirementDetails);
_checkListPointList.add(_checkListPoint);
}
CheckList _checkList = CheckList(template.name, event.description, template.advice, _checkListPointList, 0, template.checkListPointList!.length, 0, 0);
_checkListRepository.saveCheckList(_checkList);
emit(NewCheckListAdded());
} catch (e) {
emit(AddNewCheckListError());
}
}
Future<void> _showAlertDialog(ShowAlertDialogEvent event, Emitter emit) async {
emit(OpenAlertDialogState(event.checkListTemplate));
}
}

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 !