Problem with getting access to index of a map in flutter - android

I have a map<string, dynamic> ,and want to show it's components in cards by ListView.Builder, but the problem is by getting access to this map's indexes..
When running the app, it return "null" in the card!!
I have tried many solutions that I saw in StackOverFlow for a similar issues, but without a result.
Here where I identified my map:
var _item;
List listCount = [];
Map<String, dynamic> records = {};
String name;
And here where I give the var _item it's value:
MyCard(
colour: Colors.lightBlueAccent,
maker: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StreamBuilder<int>(
stream: _stopWatchTimer2.rawTime,
initialData: 0,
builder: (context, snap) {
final value = snap.data;
final displayTime = StopWatchTimer.getDisplayTime(
value,
hours: _isHours2);
_item = displayTime;
return Padding(
padding: EdgeInsets.all(5.0),
child: Text(displayTime,
style: TextStyle(
fontSize: 30.0, color: Colors.white)),
);
},
),
],
),
),
And here in the "Save" button I give the 1st parameter of the map and assign in name variable:
createAlertDialog(buildContext, context) {
TextEditingController controller;
return showDialog(
context: context,
// barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: Text(
'Type record name',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0),
),
content: TextField(
controller: controller,
onChanged: (value) {
name = value;
}),
actions: [
MaterialButton(
elevation: 5.0,
child: Text('Save'),
onPressed: () {
listCount.add(_item);
print(_item);
records[name] = _item;
print(records);
Navigator.pop(context);
},
),
MaterialButton(
elevation: 5.0,
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
}
Finally here where I tried to show it in a card by listview.builder:
Container(
color: Colors.white,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: records.length,
itemBuilder: (context, index) {
return MyCard(
colour: Colors.cyanAccent,
maker: Container(
width: 250.0,
height: 75.0,
child: Text(
'${records[index]}',
style: TextStyle(fontSize: 25.0),
textAlign: TextAlign.center,
),
),
);
},
),
),
I think the problem with the 2nd parameter of itemBuilder which it (index) because I replaced this keyword with another one randomly, and get the same result when running my app "Null".
This screenShot explain the problem:

You can get map entries as List as such:
final recordsEntries = records.entries.toList()
Then, you have a List of MapEntry and are able to access key and value associated for each item of the collection.
recordsEntries[index].key
recordsEntries[index].value

Related

How to access dynamic input fields values on button click in flutter

I am working on an attendance application where I assign wages to the workers. I want to store all the wages given to the workers into the database. But the problem is I want to access all the given values on button click. I have no idea how it can be done in flutter. I am a beginner.
I have given all the codes and the image of what output i want.
Image of Emulator
Here is my code...
ATTENDANCE SCREEN
...rest code...
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Upload Patti'),
content: SingleChildScrollView(
child: ListBody(
children: [
TextFormField(
controller: _mainWagesController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "Enter Amount",
prefixIcon: Icon(Icons.wallet, color: Colors.blue),
),
),
],
),
),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.pop(context);
newWages = _mainWagesController.text;
setState(() {});
},
child: const Text("Assign Wages"),
),
],
);
},
);
},
child: const Icon(Icons.check_circle),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.00),
child: Column(children: [
const SizedBox(
height: 20,
),
Center(
child: Text(
"Date : ${DateFormat.yMMMEd().format(DateTime.parse(widget.attendanceDate.toString()))}",
style: const TextStyle(fontSize: 20),
),
),
const SizedBox(
height: 20,
),
FutureBuilder(
future: SupervisorAttendanceServices.getAttendancesDetailsList(
widget.attendanceId),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
var data = snapshot.data['hamal'];
return ListView.builder(
itemCount: data.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return HamalAttendanceWidget(
workerId: data[index]['worker_id'],
name: data[index]['worker_name'],
wages: newWages,
masterAttendanceId: widget.attendanceId,
isPrensent: data[index]
['attendance_worker_presense']
.toString());
});
} else if (snapshot.hasError) {
return const Center(
child: Text("Something went wrong !"),
);
} else {
return const Center(child: LinearProgressIndicator());
}
},
),
]),
),
),
...rest code
widget
Widget build(BuildContext context) {
return Card(
child: Column(children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(
width: 10,
height: 50,
),
const Icon(FeatherIcons.user),
const SizedBox(
width: 20,
),
Text(
widget.name,
style: const TextStyle(fontSize: 18),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(
width: 150,
height: 60,
child: TextFormField(
// onChanged: _onChangeHandler,
initialValue: widget.wages.toString(),
decoration: const InputDecoration(
hintText: "Wages",
prefixIcon: Icon(
Icons.wallet,
color: Colors.blue,
)),
)),
],
)
]),
);
}
I suggest you use a StateManager for your application, for example GetX
is a good solution. Create a controller file like the below:
// define this enum outside of class to handle the state of the page for load data
enum AppState { initial, loading, loaded, error, empty, disabled }
Rx<AppState> pageState = AppState.initial.obs;
class AttendanceCntroller extends GetxController{
RxList<dynamic> dataList=RxList<dynamic>();
#override
void onInit() {
//you can write other codes in here to handle data
pageState(AppState.loading);
dataList.value=
SupervisorAttendanceServices.getAttendancesDetailsList(attendanceId);
pageState(AppState.loaded);
super.onInit();
}
}
and in your view(UI) page, handle it in this way:
class AttendanceView extends GetView<AttendanceCntroller>{
#override
Widget body(BuildContext context) {
// TODO: implement body
return Obx( ()=> controller.pageState.value==AppState.loading ? const
Center(child: LinearProgressIndicator()) : ListView.builder(
itemCount: controller.dataList.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return HamalAttendanceWidget(
workerId: controller.dataList['worker_id'],
name: controller.dataList['worker_name'],
wages: newWages,
masterAttendanceId: widget.attendanceId,
isPrensent: controller.dataList[index]
['attendance_worker_presense']
.toString());
})
)
}
}
for more data read the GetX link and read clean architecture with the GetX sample repository of my GitHub it have advanced management of states with GetX with dependency injection handling.
If you want to have prefilled value in TextFormField, you can either use initialValue or controller parameter.
The value of controller parameter will help you to get/update the value of TextFormField.
For controller parameter refer below.
TextEditingController controller = TextEditingController(text: 'This is text will be pre-filled in TextFormField');
...
TextFormField(
controller: controller,
);
Create List or Map of those controllers.
List<TextEditingController> listOfControllers = [ controller1, controlle2,...];
Use for loop through this List on onClick() method of Button.
ElevatedButton(
onPressed: () {
for(var controllerItem in listOfControllers) {
print(controllerItem.text); // the value of TextFormField
}
},
)

Update the SubTitle of a listview without refreshing in Flutter

At start, I load data from the database that populates the ListView. These data is displayed on the ListView title and subtitle. When a user taps on one of the items on the list, a showModalBottomSheet popups with fields to update the list(index). This update is carried out successfully but on the close of the showModalBottomSheet, the values on each ListView item refreshes to default (data from database).
Please, how can I update the ListView items without the ListView refreshing to initial data value?
Widget _buildSubjects(BuildContext context, int index) {
response = getFieldData(_snapshot!.data[index]);
return ListTile(
trailing: IconButton(
icon: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Text(
_snapshot!.data[index]['name']
.toString()
.toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
),
Form(
key: _scoreForm,
child: Column(
children: [
scoreFields(_snapshot!.data[index]),
SizedBox(
height: 10.0,
),
ElevatedButton(
onPressed: () {
if (!_scoreForm.currentState!.validate())
return;
_scoreForm.currentState!.save();
setState(() {
response = "New Value";
});
//close bottomsheet
Navigator.pop(context);
},
child: Text("Save Score"),
),
],
),
),
],
),
),
);
},
);
},
),
title: Text(
_snapshot!.data[index]['name'].toString().toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.w400,
),
),
subtitle: Text(
response,
),
onTap: () {},
);
}
You may wrap your ListTile with ValueListenableBuilder like below:
ValueNotifier<bool> newData = ValueNotifier(false);
ValueListenableBuilder<bool>(
valueListenable: newData,
builder: (context, value, child) {
return ListTile(
trailing: IconButton(
icon: Icon(Icons.add), //... rest of your code
and instead of calling
setState(() {
response = "New Value";
});
call below without setState
response = "New Value";
newData.value = !newData.value;
so now the state of the ListTile will be updated and no need to setState for the complete listview.
To update the data in Listtile(title and subtitle) you need to use Stream and Streambuilder which will update the data based on stream change from your database.

Calling multiple functions in FutureBuilder causes an error

I am retrieving data from Firestore in the form of two functions (_onpressed() and _drname()) and called both of them in FutureBuilder.
Function 1 is
Future _onPressed() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Messages')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['Message']}');
String msg = json.encode(documentSnapshot.data()['Message']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No Prescription from doctor yet';
}}
Function 2 is
Future _drname() async {
if (widget.brew.id == currentid.userid()) {
return await db
.collection('Drname')
.doc(widget.brew.id)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('${documentSnapshot.data()['name']}');
String msg = json.encode(documentSnapshot.data()['name']);
return msg;
} else {
print('Document does not exist on the database');
}
// var a= documentSnapshot.data()['Message'];
});
} else {
return 'No';
}}
Calling these functions in FutureBuilder like this
Widget _messagePannel() {
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: const EdgeInsets.only(right: 17.0),
child: TextButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Call()),
);
},
icon: Icon(
Icons.video_call,
color: Colors.white,
size: 30.0,
),
label: Text(''),
),
)
],
title: Text(
'Prescrption',
style: TextStyle(fontFamily: 'RussoOne', fontSize: 22.0),
),
backgroundColor: Colors.green[900],
elevation: 0.0,
centerTitle: true,
),
body: Container(
decoration: image,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
color: Colors.black,
child: Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0.0, 4.0, 4.0, 4.0),
child: Wrap(
children: [
Center(
child: Text(
'${snapshot.data[0]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
Center(
child: Text(
'${snapshot.data[1]} ',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: 'RussoOne',
color: Colors.white,
letterSpacing: 0.8,
fontSize: 18.0,
backgroundColor: Colors.black),
),
),
],
),
)),
),
),
),
],
),
),
),
);
});}
Getting This error from the Debug Console
The following NoSuchMethodError was thrown building FutureBuilder<List>(dirty, state: _FutureBuilderState<List>#44f46):
The method '[]' was called on null.
Receiver: null
Tried calling:
When using snapshot, the initial value for the data property is null (since Future has no result until you receive the response), so using it straight away as you do it in the code (e.g. snapshot.data[1]) should be avoided.
To cope with that, first of all you should check if the data is not null. For that, snapshot has a dedicated method snapshot.hasData, for instance:
return FutureBuilder(
future: Future.wait([_onPressed(),_drname()]),
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator(); // E.g. Show loader if there is no data yet
}
return Scaffold(...); // Return the widget you have now
},
);

Flutter Firestore How to list people I only have chat history with?

This is a part of my chat homepage & it lists every user in my firestore database. But I want to make it list the only people I contacted with.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
title: Text(
'Sohbet',
style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),
),
iconTheme: IconThemeData(
color: Colors.black, //change your color here
),
centerTitle: true,
actions: <Widget>[
PopupMenuButton<Choice>(
onSelected: onItemMenuPress,
itemBuilder: (BuildContext context) {
return choices.map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Row(
children: <Widget>[
Icon(
choice.icon,
color: primaryColor,
),
Container(
width: 10.0,
),
Text(
choice.title,
style: TextStyle(color: primaryColor),
),
],
));
}).toList();
},
),
],
),
body: WillPopScope(
child: Stack(
children: <Widget>[
// List
Container(
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('users')
.limit(_limit)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(themeColor),
),
);
} else {
return ListView.builder(
padding: EdgeInsets.all(10.0),
itemBuilder: (context, index) =>
buildItem(context, snapshot.data.documents[index]),
itemCount: snapshot.data.documents.length,
controller: listScrollController,
);
}
},
),
),
// Loading
Positioned(
child: isLoading ? const Loading() : Container(),
)
],
),
),
);
}
Widget buildItem(BuildContext context, DocumentSnapshot document) {
if (document.data()['id'] == _auth.currentUser.uid) {
return Container();
} else {
return Container(
child: FlatButton(
child: Row(
children: <Widget>[
Material(
child: document.data()['photoUrl'] != null
? CachedNetworkImage(
placeholder: (context, url) => Container(
child: CircularProgressIndicator(
strokeWidth: 1.0,
valueColor:
AlwaysStoppedAnimation<Color>(themeColor),
),
width: 50.0,
height: 50.0,
padding: EdgeInsets.all(15.0),
),
imageUrl: document.data()['photoUrl'],
width: 50.0,
height: 50.0,
fit: BoxFit.cover,
)
: Icon(
Icons.account_circle,
size: 50.0,
color: greyColor,
),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
clipBehavior: Clip.hardEdge,
),
Flexible(
child: Container(
child: Column(
children: <Widget>[
Container(
child: Text(
'${document.data()['nickname']}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 5.0),
),
/*Container(
child: Text(
'About me: ${document.data()['aboutMe'] ?? 'Not available'}',
style: TextStyle(color: primaryColor),
),
alignment: Alignment.centerLeft,
margin: EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 0.0),
)*/
],
),
margin: EdgeInsets.only(left: 20.0),
),
),
],
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: document.id,
peerAvatar: document.data()['photoUrl'],
)));
},
color: greyColor2,
padding: EdgeInsets.fromLTRB(25.0, 10.0, 25.0, 10.0),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
),
margin: EdgeInsets.only(bottom: 10.0, left: 5.0, right: 5.0),
);
}
}
Pics of my firestore data paths like:
Users collection
Messages collection
An example message doc
Tried:
set({friends array}) for per user in google sign in auth function but everytime I sign in it resets that array so there is no point updating that array because it resets that friends/contacts list everytime user signs in.
First you need to store the friends information, you can add a simple if check after google sign in auth function that if a document exists do not create a new document that would solve your resetting problem.
Assuming you have a currentUser object with firestore document id's
final friends = (await FirebaseFirestore.instance.collection("users").doc(currentUser.id).get()).data;
Get the friends list for the current user, you can convert it to list of user ids by mapping.
stream: FirebaseFirestore.instance
.collection('users')
.where("id",whereIn: friendsIds)
.limit(_limit)
.snapshots(),
i know this is super late but it might be useful for future search.
in every chat room(in your case it is messages), you need to create a field members which has a type of array or map. Inside that array, you need to store your id and the id of the person you are chatting with.
After that, you can just query the chat rooms .where((room) => room.members.contains(//your_id)).

Flutter: SnackBar not displayed after calling setState() method

I'm implementing this products app where a user can add a product from his wish list and add it to their cart. Once the user clicks the add to cart button, I want to delete the product from the screen and display a "success" Snackbar.
Since the products are loaded and displayed from FireBase Firestore, I delete the item and call setState({}); so that the list on the screen will be updated. The problem is that the SnackBar that comes right after setState({}); isn't shown.
I assume it is because the widget tree is rebuilt so the current state and context are "gone".
I tried finding some information online but haven't managed to find anything useful. I also tried to make a workaround with a bool flag that will be set once the user clicks the "Add to cart" button using and on setState the flag will be true one time to show the SnackBar when the widget tree is rebuilt and then turn the flag back to off but it didn't work as well.
What am I missing? How can I display a SnackBar after calling setState({})?
here is my code: (line in question marked with FIXME:)
slidable package installation
final GlobalKey _repaintBoundaryKey = GlobalKey();
final GlobalKey<ScaffoldState> _scaffoldKeyWishList = new GlobalKey<ScaffoldState>();
final Center _circularProgressIndicator = Center(
child: SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreen[800]),
)
),
);
#override
Widget build(BuildContext context) {
return Material(
child: FutureBuilder(
future: FirebaseFirestore.instance.collection("Wishlists").doc(FirebaseAuth.instance.currentUser.uid).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> wishListSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done) {
return _circularProgressIndicator;
} else if (!wishListSnapshot.hasData ||
0 == wishListSnapshot.data.data()['Wishlist'].length) {
return globals.emptyListErrorScreen(context, 'Wishlist');
}
int totalProducts = wishListSnapshot.data.data()['Wishlist'].length;
return Scaffold(
key: _scaffoldKeyWishList,
backgroundColor: Colors.lightGreen[800],
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: ListView.builder(
itemCount: totalProducts * 2,
shrinkWrap: true,
padding: const EdgeInsets.all(16),
itemBuilder: (BuildContext _context, int i) {
if (i >= 2 * totalProducts) {
return null;
}
if (i.isOdd) {
return Divider(
color: Colors.green,
thickness: 1.0,
);
}
var wishlistIdData = wishListSnapshot.data.data()['Wishlist'];
String productID = wishlistIdData[i ~/ 2];
return FutureBuilder(
future: FirebaseFirestore.instance.collection("Products").doc(productID).get(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> productSnapshot) {
if (wishListSnapshot.connectionState != ConnectionState.done || !productSnapshot.hasData) {
return _circularProgressIndicator;
}
var productData = productSnapshot.data.data()['Product'];
String prodName = productData['name'];
String prodPrice = productData['price'];
String prodDate = productData['date'];
return Slidable(
actionPane: SlidableDrawerActionPane(),
actionExtentRatio: 0.22,
direction: Axis.horizontal,
actions: <Widget>[
//add to cart
IconSlideAction(
caption: 'Add to cart',
color: Colors.transparent,
foregroundColor: Colors
.amberAccent,
icon: Icons.add_shopping_cart,
onTap: () async {
globals.userCart.add(
globals.Product(
productID,
FirebaseAuth.instance.currentUser.uid,
prodName,
double.parse(prodPrice),
prodDate,
[],
"",
"")
);
///removing product from wishlist
List toRemove = [];
toRemove.add(productID);
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.get()
.then((value) async {
List<dynamic> list = List
.from(value
.data()['Wishlist']);
list
..removeWhere((e) =>
toRemove.contains(e));
await FirebaseFirestore.instance
.collection('Wishlists')
.doc(FirebaseAuth.instance.currentUser.uid)
.update(
{'Wishlist': list});
});
setState(() {
///to update the list on screen
});
//FIXME: snackbar not displayed after setState!
///showing snackbar upon completion
_scaffoldKeyWishList
.currentState
.showSnackBar(
SnackBar(
content: Text(
'Product Successfully Added to Cart!',
style: GoogleFonts
.lato(
fontSize: 13.0,
color: Colors
.white
),
),
behavior: SnackBarBehavior
.floating,
action: SnackBarAction(
label: 'Checkout',
textColor: Colors
.lime,
onPressed: () =>
showDialog(
context: context,
builder: (
BuildContext context) {
return CustomDialogBox();
},
),
),
)
);
},
),
],
child: ListTile(
title: Text(prodName,
style: GoogleFonts.lato(
fontSize: 18.0,
color: Colors.black,
),
),
subtitle: Text(prodPrice + "\$",
style: GoogleFonts.lato(
fontSize: 13.5,
color: Colors.grey,
),
),
visualDensity: VisualDensity
.adaptivePlatformDensity,
),
);
},
);
},
),
)
)
]
)
)
);
}
)
);
}
In my case I was calling setState method before build method complete process of building widgets.
You can face this error if you are showing snack bar or alert dialog before the completion of build method and in many other cases. so in such situation use below call back function.
WidgetsBinding.instance.addPostFrameCallback((_) {
// add your snackbar code here
});
or You can also use SchedulerBinding which does the same.
SchedulerBinding.instance.addPostFrameCallback((_) {
// add your code here of snackbar.
});
or you can try this too (I am not sure about this one)
if(mounted){
//add your code here of snackbar
}
CREDITS

Categories

Resources