how to update page state after Navigator.pop() from an alert box
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have 2 pages in my Flutter app - ShoppingListsPage and ItemsListPage. I have a FloatingActionButton in ShoppingListsPage clicking which will take the user to ItemsListPage where he can add items from a ListView to a shopping list and then save the list by clicking a button in the AppBar. Once the user clicks the Done button in the AppBar, I display an AlertDialog dialog box to ask the user for a name for the list. Once the user enters the list name and clicks Save button in the dialog, I save the list details in an SQLite database(I'm using sqflite plugin for database interaction) and then want to move the user back to ShoppingListsPage where the newly created list has to be displayed.
Given this context, What I observe is that when I save the list to the database and navigate to ShoppingListsPage using Navigate.pop(context), the code to fetch the shopping lists from the database is executed but it does not retrieve the latest addition and hence the ListView in ShoppingListsPage is not updated with the latest changes. However, if I navigate to some other page and come back, the newly added list is displayed. It looks like the fetch from the database in ShoppingListsPage is happening before the data is persisted in the database. How do I make sure that the fetch is successful(with the latest data) from the database?
On a related note, what is a better way to make sure that the async function I have to save the data to the database is called and completed before Navigator.pop(context) takes the user to the previous screen? All my functions to interact with the SQLite database are async functions.
Here's the code to display the dialog in ItemsList page, save the data and navigate back to ShoppingListsPage:
_showListNameDialog() async {
final textController = new TextEditingController();
String retVal = await showDialog<String>(
context: context,
child: AlertDialog(
contentPadding: EdgeInsets.all(12.0),
content: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'List Name',
hintText: 'Monthly groceries'
),
controller: textController,
),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: (){
Navigator.pop(context);
},
child: Text('Cancel')
),
FlatButton(
onPressed: (){
addShoppingListItemsToDB(textController.text, shoppingListItemMap);
Navigator.pop(context, textController.text);
},
child: Text('Save')
)
],
)
);
Navigator.pop(context);
setState(() {
});
}
Here's the code in ShoppingListsPage to fetch and display the data:
Future<List<ShoppingList>> getShoppingLists() async {
DBHelper dbClient = DBHelper();
return dbClient.getShoppingLists();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Shopping Lists'),
),
body: Container(
padding: EdgeInsets.all(12.0),
child: FutureBuilder<List<ShoppingList>>(
future: getShoppingLists(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
String listName = snapshot.data[index].listName;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: CircleAvatar(
child: Text(listName==''?'u':listName[0]),
),
title: Text(snapshot.data[index].listName, style: TextStyle(fontSize: 18.0),),
subtitle: Text('Created at ${snapshot.data[index].createdAt}', style: TextStyle(color: Colors.grey),),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingListItemsPage(list_name: snapshot.data[index].listName,))
);
},
),
Divider()
]
);
}
);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Container(alignment: AlignmentDirectional.center, child: CircularProgressIndicator(),);
}
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
},
child: Icon(Icons.add),),
);
}
dart flutter sqflite
add a comment |
I have 2 pages in my Flutter app - ShoppingListsPage and ItemsListPage. I have a FloatingActionButton in ShoppingListsPage clicking which will take the user to ItemsListPage where he can add items from a ListView to a shopping list and then save the list by clicking a button in the AppBar. Once the user clicks the Done button in the AppBar, I display an AlertDialog dialog box to ask the user for a name for the list. Once the user enters the list name and clicks Save button in the dialog, I save the list details in an SQLite database(I'm using sqflite plugin for database interaction) and then want to move the user back to ShoppingListsPage where the newly created list has to be displayed.
Given this context, What I observe is that when I save the list to the database and navigate to ShoppingListsPage using Navigate.pop(context), the code to fetch the shopping lists from the database is executed but it does not retrieve the latest addition and hence the ListView in ShoppingListsPage is not updated with the latest changes. However, if I navigate to some other page and come back, the newly added list is displayed. It looks like the fetch from the database in ShoppingListsPage is happening before the data is persisted in the database. How do I make sure that the fetch is successful(with the latest data) from the database?
On a related note, what is a better way to make sure that the async function I have to save the data to the database is called and completed before Navigator.pop(context) takes the user to the previous screen? All my functions to interact with the SQLite database are async functions.
Here's the code to display the dialog in ItemsList page, save the data and navigate back to ShoppingListsPage:
_showListNameDialog() async {
final textController = new TextEditingController();
String retVal = await showDialog<String>(
context: context,
child: AlertDialog(
contentPadding: EdgeInsets.all(12.0),
content: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'List Name',
hintText: 'Monthly groceries'
),
controller: textController,
),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: (){
Navigator.pop(context);
},
child: Text('Cancel')
),
FlatButton(
onPressed: (){
addShoppingListItemsToDB(textController.text, shoppingListItemMap);
Navigator.pop(context, textController.text);
},
child: Text('Save')
)
],
)
);
Navigator.pop(context);
setState(() {
});
}
Here's the code in ShoppingListsPage to fetch and display the data:
Future<List<ShoppingList>> getShoppingLists() async {
DBHelper dbClient = DBHelper();
return dbClient.getShoppingLists();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Shopping Lists'),
),
body: Container(
padding: EdgeInsets.all(12.0),
child: FutureBuilder<List<ShoppingList>>(
future: getShoppingLists(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
String listName = snapshot.data[index].listName;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: CircleAvatar(
child: Text(listName==''?'u':listName[0]),
),
title: Text(snapshot.data[index].listName, style: TextStyle(fontSize: 18.0),),
subtitle: Text('Created at ${snapshot.data[index].createdAt}', style: TextStyle(color: Colors.grey),),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingListItemsPage(list_name: snapshot.data[index].listName,))
);
},
),
Divider()
]
);
}
);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Container(alignment: AlignmentDirectional.center, child: CircularProgressIndicator(),);
}
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
},
child: Icon(Icons.add),),
);
}
dart flutter sqflite
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53
add a comment |
I have 2 pages in my Flutter app - ShoppingListsPage and ItemsListPage. I have a FloatingActionButton in ShoppingListsPage clicking which will take the user to ItemsListPage where he can add items from a ListView to a shopping list and then save the list by clicking a button in the AppBar. Once the user clicks the Done button in the AppBar, I display an AlertDialog dialog box to ask the user for a name for the list. Once the user enters the list name and clicks Save button in the dialog, I save the list details in an SQLite database(I'm using sqflite plugin for database interaction) and then want to move the user back to ShoppingListsPage where the newly created list has to be displayed.
Given this context, What I observe is that when I save the list to the database and navigate to ShoppingListsPage using Navigate.pop(context), the code to fetch the shopping lists from the database is executed but it does not retrieve the latest addition and hence the ListView in ShoppingListsPage is not updated with the latest changes. However, if I navigate to some other page and come back, the newly added list is displayed. It looks like the fetch from the database in ShoppingListsPage is happening before the data is persisted in the database. How do I make sure that the fetch is successful(with the latest data) from the database?
On a related note, what is a better way to make sure that the async function I have to save the data to the database is called and completed before Navigator.pop(context) takes the user to the previous screen? All my functions to interact with the SQLite database are async functions.
Here's the code to display the dialog in ItemsList page, save the data and navigate back to ShoppingListsPage:
_showListNameDialog() async {
final textController = new TextEditingController();
String retVal = await showDialog<String>(
context: context,
child: AlertDialog(
contentPadding: EdgeInsets.all(12.0),
content: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'List Name',
hintText: 'Monthly groceries'
),
controller: textController,
),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: (){
Navigator.pop(context);
},
child: Text('Cancel')
),
FlatButton(
onPressed: (){
addShoppingListItemsToDB(textController.text, shoppingListItemMap);
Navigator.pop(context, textController.text);
},
child: Text('Save')
)
],
)
);
Navigator.pop(context);
setState(() {
});
}
Here's the code in ShoppingListsPage to fetch and display the data:
Future<List<ShoppingList>> getShoppingLists() async {
DBHelper dbClient = DBHelper();
return dbClient.getShoppingLists();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Shopping Lists'),
),
body: Container(
padding: EdgeInsets.all(12.0),
child: FutureBuilder<List<ShoppingList>>(
future: getShoppingLists(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
String listName = snapshot.data[index].listName;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: CircleAvatar(
child: Text(listName==''?'u':listName[0]),
),
title: Text(snapshot.data[index].listName, style: TextStyle(fontSize: 18.0),),
subtitle: Text('Created at ${snapshot.data[index].createdAt}', style: TextStyle(color: Colors.grey),),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingListItemsPage(list_name: snapshot.data[index].listName,))
);
},
),
Divider()
]
);
}
);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Container(alignment: AlignmentDirectional.center, child: CircularProgressIndicator(),);
}
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
},
child: Icon(Icons.add),),
);
}
dart flutter sqflite
I have 2 pages in my Flutter app - ShoppingListsPage and ItemsListPage. I have a FloatingActionButton in ShoppingListsPage clicking which will take the user to ItemsListPage where he can add items from a ListView to a shopping list and then save the list by clicking a button in the AppBar. Once the user clicks the Done button in the AppBar, I display an AlertDialog dialog box to ask the user for a name for the list. Once the user enters the list name and clicks Save button in the dialog, I save the list details in an SQLite database(I'm using sqflite plugin for database interaction) and then want to move the user back to ShoppingListsPage where the newly created list has to be displayed.
Given this context, What I observe is that when I save the list to the database and navigate to ShoppingListsPage using Navigate.pop(context), the code to fetch the shopping lists from the database is executed but it does not retrieve the latest addition and hence the ListView in ShoppingListsPage is not updated with the latest changes. However, if I navigate to some other page and come back, the newly added list is displayed. It looks like the fetch from the database in ShoppingListsPage is happening before the data is persisted in the database. How do I make sure that the fetch is successful(with the latest data) from the database?
On a related note, what is a better way to make sure that the async function I have to save the data to the database is called and completed before Navigator.pop(context) takes the user to the previous screen? All my functions to interact with the SQLite database are async functions.
Here's the code to display the dialog in ItemsList page, save the data and navigate back to ShoppingListsPage:
_showListNameDialog() async {
final textController = new TextEditingController();
String retVal = await showDialog<String>(
context: context,
child: AlertDialog(
contentPadding: EdgeInsets.all(12.0),
content: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
labelText: 'List Name',
hintText: 'Monthly groceries'
),
controller: textController,
),
)
],
),
actions: <Widget>[
FlatButton(
onPressed: (){
Navigator.pop(context);
},
child: Text('Cancel')
),
FlatButton(
onPressed: (){
addShoppingListItemsToDB(textController.text, shoppingListItemMap);
Navigator.pop(context, textController.text);
},
child: Text('Save')
)
],
)
);
Navigator.pop(context);
setState(() {
});
}
Here's the code in ShoppingListsPage to fetch and display the data:
Future<List<ShoppingList>> getShoppingLists() async {
DBHelper dbClient = DBHelper();
return dbClient.getShoppingLists();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Shopping Lists'),
),
body: Container(
padding: EdgeInsets.all(12.0),
child: FutureBuilder<List<ShoppingList>>(
future: getShoppingLists(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
String listName = snapshot.data[index].listName;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(
leading: CircleAvatar(
child: Text(listName==''?'u':listName[0]),
),
title: Text(snapshot.data[index].listName, style: TextStyle(fontSize: 18.0),),
subtitle: Text('Created at ${snapshot.data[index].createdAt}', style: TextStyle(color: Colors.grey),),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingListItemsPage(list_name: snapshot.data[index].listName,))
);
},
),
Divider()
]
);
}
);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Container(alignment: AlignmentDirectional.center, child: CircularProgressIndicator(),);
}
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
},
child: Icon(Icons.add),),
);
}
dart flutter sqflite
dart flutter sqflite
asked Jan 4 at 14:37
Rakesh KRakesh K
3,070133749
3,070133749
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53
add a comment |
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53
add a comment |
1 Answer
1
active
oldest
votes
You could use await
keyword to wait until the user pop the Widget
.
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
setState(() {});
},
child: Icon(Icons.add),),
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54041012%2fhow-to-update-page-state-after-navigator-pop-from-an-alert-box%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could use await
keyword to wait until the user pop the Widget
.
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
setState(() {});
},
child: Icon(Icons.add),),
add a comment |
You could use await
keyword to wait until the user pop the Widget
.
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
setState(() {});
},
child: Icon(Icons.add),),
add a comment |
You could use await
keyword to wait until the user pop the Widget
.
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
setState(() {});
},
child: Icon(Icons.add),),
You could use await
keyword to wait until the user pop the Widget
.
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ItemListPage(listName: 'Untitled',listItems: null,)));
setState(() {});
},
child: Icon(Icons.add),),
answered Jan 4 at 14:53
diegoveloperdiegoveloper
15.7k12636
15.7k12636
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54041012%2fhow-to-update-page-state-after-navigator-pop-from-an-alert-box%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can't you just call navigator pop on a callback from the data save, eg addShoppingListItemsToDB (or make that synchronous) IF it's a requirement that you shouldn't be able to go back until it's saved ?
– Ian
Jan 4 at 14:53