In my Flutter application I am using Provider
version 4.0.4 to manage the state of my app. In basic terms, my app will list down the nearby companies with their rating. users can select a organisation, open it and add their rating as well, so the final rating will be updated. I am using the Consumer
concept in Provider
to handle the tasks.
- In
NearByPlacesPage
class I am listing down the companies around me with rating information. User can click on a company and they will be taken toOrganizationPage
page. - In
OrganizationPage
class, the rating is displayed again. user can add their rating to the system. Then the rating information in bothOrganizationPage
page andNearByPlacesPage
(back page) need to be updated.
The issue is, when the user update the rating, the rating in OrganizationPage
get updated but not NearByPlacesPage
in back stack. When we go back to NearByPlacesPage
, we can clearly see the old rating values. The page need to be reloaded to get updated values.
Below are the important sections in my code
NearByPlacesPage
class NearByPlacesPage extends StatelessWidget {
int orgTypeID;
String orgTypeName;
NearByPlacesPage(this.orgTypeID, this.orgTypeName);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => RatingService()),
],
child: SingleChildScrollView(
child: _NearByPlacesPageUI(orgTypeID, orgTypeName),
),
),
appBar: AppBar(
title: Text(orgTypeName),
),
);
}
}
class _NearByPlacesPageUI extends StatefulWidget {
int orgTypeID;
String orgTypename;
_NearByPlacesPageUI(this.orgTypeID, this.orgTypename);
@override
State<StatefulWidget> createState() {
return _NearByPlacesPageState();
}
}
class _NearByPlacesPageState extends State<_NearByPlacesPageUI> {
@override
Widget build(BuildContext context) {
Consumer<RatingService>(builder: (context, data, child){
return Flexible(
child: ListView.builder(
itemCount: orgList.length,
itemBuilder:(BuildContext context, int index) {
Organization organization = orgList[index];
if (organization.isDisabled != true) {
RatingValue ratingValue = data.getData();
return Container(
margin: EdgeInsets.only(
top: 5, left: 5, right: 5),
child: _buildPlace(organization, ratingValue));
} else {
return Container();
}
},),
);
},);
}
}
OrganizationPage
class OrganizationPage extends StatelessWidget {
Organization organization;
String orgTypeName;
OrganizationPage(this.organization, this.orgTypeName);
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: _OrganizationPageUI(organization, orgTypeName),
),
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(organization.name),
),
);
}
}
class _OrganizationPageUI extends StatefulWidget {
Organization organization;
String orgTypeName;
_OrganizationPageUI(this.organization, this.orgTypeName);
@override
State<StatefulWidget> createState() {
return _OrganizationPageState();
}
}
class _OrganizationPageState extends State<_OrganizationPageUI> {
@override
Widget build(BuildContext context) {
Consumer<RatingService>(
builder: (context, data, child) {
Consumer<RatingService>(
return Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 10, left: 10),
child: Text(daa.getData()
style: Theme.of(context).textTheme.bodyText2.apply(color: Colors.grey),
),
),
],
);
),
}
}
}
In OrganizationPage there is a AlerDialog
, which allows the user to rate and save. When saved, it will call another method which will reload the data.
Widget _ratingDialog(double _rating) {
RatingService _ratingService =
Provider.of<RatingService>(context, listen: false);
Rating _rating = _ratingService.returnRating();
double _ratingValue = _ratingService.returnRating().rating;
return AlertDialog(
title: const Text("Your Rating"),
actions: [
new FlatButton(
child: const Text("Save"),
//onPressed: () => Navigator.pop(context),
onPressed: () async {
Rating rating = Rating(
idrating:
_rating.idrating != null ? _rating.idrating : null,
user: _user,
organization: widget.organization,
rating: _ratingValue,
dateCreated: DateTime.now().millisecondsSinceEpoch,
lastUpdated: DateTime.now().millisecondsSinceEpoch);
await _ratingService.saveOrUpdateRating(rating, authToken);
_loadRatingByUserAndOrganization(authToken);
_loadRatingValueByOrganization(authToken);
Navigator.pop(context);
},
),
],
);
}
Future _loadRatingByUserAndOrganization(String authToken) {
RatingService _ratingService =Provider.of<RatingService>(context, listen: false);
return _ratingService.getRatingByUserAndOrganization(
_authService.getDatabaseUser().user.iduser,
widget.organization.idorganization,
authToken);
}
RatingService
This is the class which is responsible for calling notifyListeners()
. It will be triggered by the above AlertDialog
and the expected behaviour is to reload data in both OrganizationPage
and NearByPlacesPage
class RatingService with ChangeNotifier {
List<RatingValue> _ratingValueList ;
List<RatingValue> getData()
{
return _ratingValueList;
}
//Load rating by user and Organization
Future<void> getRatingByUserAndOrganization(int idUser, int organizationID, String authToken) async {
try {
var data = await http.get(
_navLinks.getRatingByUserAndOrganization(idUser, organizationID),
headers: {HttpHeaders.authorizationHeader: "Bearer $authToken"},
);
print(data.body);
_rating = Rating.fromJson(convert.json.decode(data.body));
notifyListeners();
} catch (error) {
print(error);
throw error;
}
}
}
What I have I done wrong?