0

I am working on a Flutter project which is a tricycle booking system that also uses Realtime Database in Firebase. If the ride status of the passenger has been accepted by the driver, an audio or notify sound will be executed then a modal popup/dialog will be displayed.

Upon trying, these two functionalities have been executed indefinitely and multiple times as long as the ride status of the passenger is accepted. How do I implement it once only and what is the reason behind it because I am not using any loop for this?

Here are the updated code for this method:

 saveRideRequestInformation() //Ride Request Code { //1. save the Ride Request Information referenceRideRequest = FirebaseDatabase.instance.ref().child("All Ride Requests").push(); // Creates unique ID String? rideKey = referenceRideRequest!.key.toString(); var originLocation = Provider.of<AppInfo>(context, listen: false).userPickUpLocation; var destinationLocation = Provider.of<AppInfo>(context, listen: false).userDropOffLocation; Map originLocationMap = { //key:value "latitude": originLocation!.locationLatitude.toString(), "longitude": originLocation!.locationLongitude.toString(), }; Map destinationLocationMap = { //key:value "latitude": destinationLocation!.locationLatitude.toString(), "longitude": destinationLocation!.locationLongitude.toString(), }; Map userInformationMap = { "origin": originLocationMap, "destination": destinationLocationMap, "time": DateTime.now().toString(), "username": userModelCurrentInfo!.username!, "email": userModelCurrentInfo!.email!, "id": userModelCurrentInfo!.id!, "requestId": rideKey, "originAddress": originLocation.locationName, "destinationAddress": destinationLocation.locationName, "driverId": "waiting", "notified" : "false", }; referenceRideRequest!.set(userInformationMap); tripRideRequestInfoStreamSubscription = referenceRideRequest!.onValue.listen((eventSnap) async // getting updates in real time { if(eventSnap.snapshot.value == null) { return; } if ((eventSnap.snapshot.value as Map)["driverPlateNum"] != null) //!! GAWING CAR DETAILS/ PLATE NUMBER { setState(() { driverTricDetails = (eventSnap.snapshot.value as Map)["driverPlateNum"].toString(); }); } if ((eventSnap.snapshot.value as Map)["driverPhone"] != null) //!! GET PHONE NUMBER { setState(() { driverPhone = (eventSnap.snapshot.value as Map)["driverPhone"].toString(); }); } if ((eventSnap.snapshot.value as Map)["notified"] != null) //!! GET PHONE NUMBER { setState(() { notified = (eventSnap.snapshot.value as Map)["notified"].toString(); }); } if ((eventSnap.snapshot.value as Map)["driverName"] != null) //!! GET FNAME { setState(() { driverName = (eventSnap.snapshot.value as Map)["driverName"].toString(); }); } if((eventSnap.snapshot.value as Map)["status"] != null) { setState(() { userRideRequestStatus = (eventSnap.snapshot.value as Map)["status"].toString(); }); } if((eventSnap.snapshot.value as Map)["driverLocation"] != null) { double driverCurrentPositionLat = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["latitude"].toString()); double driverCurrentPositionLng = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["longitude"].toString()); LatLng driverCurrentPositionLatLng = LatLng(driverCurrentPositionLat, driverCurrentPositionLng); if(userRideRequestStatus != null) { isVisible= !isVisible; showUIForAssignedDriverInfo(); //when status = accepted if(userRideRequestStatus == "accepted" && notified == "false") { FirebaseDatabase.instance.ref() .child("All Ride Requests") .child(rideKey) .child("notified") .set("true"); passengerIsOfflineNow(); assignedDriverModal(); updateArrivalTimeToUserPickupLocation(driverCurrentPositionLatLng); } //when status = arrived if(userRideRequestStatus == "arrived") { setState(() { driverRideStatus = "Your driver has arrived."; }); } //when status = onTrip if(userRideRequestStatus == "onTrip") { updateReachingTimeToUserDropOffLocation(driverCurrentPositionLatLng); } //when status = ended if(userRideRequestStatus == "ended") { if((eventSnap.snapshot.value as Map)["fareAmount"] != null) { double fareAmount = double.parse((eventSnap.snapshot.value as Map)["fareAmount"].toString()); var response = await showDialog( context: context, barrierDismissible: false, builder: (BuildContext c) => PayFareAmountDialog( fareAmount: fareAmount, ), ); if(response == "cashPayed") { //user can rate the driver if((eventSnap.snapshot.value as Map)["driverId"] != null) { String assignedDriverId = (eventSnap.snapshot.value as Map)["driverId"].toString(); Navigator.push(context, MaterialPageRoute(builder: (c)=> RateDriverScreen( assignedDriverId: assignedDriverId, ))); referenceRideRequest!.onDisconnect(); tripRideRequestInfoStreamSubscription!.cancel(); } } } } } } }); onlineNearbyAvailableDriversList = GeoFireAssistant.activeNearbyAvailableDriversList; //searchNearestOnlineDrivers(); } 

1 Answer 1

2

Its because of the snapshot listener that runs when the driver location updates. As the driver location updates, it loops through everything in your if statement. This specifically:

if((eventSnap.snapshot.value as Map)["driverLocation"] != null) { double driverCurrentPositionLat = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["latitude"].toString()); double driverCurrentPositionLng = double.parse((eventSnap.snapshot.value as Map)["driverLocation"]["longitude"].toString()); LatLng driverCurrentPositionLatLng = LatLng(driverCurrentPositionLat, driverCurrentPositionLng); if(userRideRequestStatus != null) { isVisible= !isVisible; showUIForAssignedDriverInfo(); //when status = accepted. !! this is my concern !! if(userRideRequestStatus == "accepted") ... 

What you could consider doing is adding a flag in the eventSnap.snapshot.value to say something along the lines of notified. And then after you run the if(userRideRequestStatus == "accepted") statement, flip the notified value to true. This would then change your accepted if statement from if(userRideRequestStatus == "accepted") to if(userRideRequestStatus == "accepted" && !driverNotified).

Sign up to request clarification or add additional context in comments.

11 Comments

what do you mean by adding a flag?
Can you give an example, I am confused. :( I only need to display the dialog when the status is accepted, I can't think of any other conditions...
I am saying you can add a value to your RTDB that you store as false until you send your driver a notification and then flip that flag to true so your code knows that you have already notified the driver. This if value keeps getting run if((eventSnap.snapshot.value as Map)["driverLocation"] != null) and then runs the if(userRideRequestStatus == "accepted") since its contained within it.
I get the idea now but can you give an example of codes on how could I implement it?
Yup same concept. Since you are doing it locally, you don't have to wait for the stream to update with the new value. So since there is probably 5 driver location updates between you notifying the driver (and setting driverNotified in the DB), you would need to wait for the stream to catch up to that new driverNotified value. If you set it locally, it would catch it prior to the stream catching up.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.