StreamBuilder doesn't rebuild after Navigator.pop
When you push and after pop a page, the build metod doesn't restart. I found the same problem with the FlutterBluetoothSerial.instance.onStateChanged() stream and the solution that I found is to add the stream to a local static final variable and use it instead of calling every time the original method (you can do that only if the stream is a broadcast one I think).
Solution example:
class ExampleClass {
static final Stream<LatLng> locationStream = LocationService().locationStream;
}
class SelfUpdatingMap extends StatelessWidget {
...
@override
Widget build(BuildContext context) => StreamBuilder<LatLng>(
stream: ExampleClass.locationStream,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.hasError || asyncSnapshot.data == null) {
return Text('Loading...');
}
try {
_controller?.move(asyncSnapshot.data, 18);
} catch (ignored) {}
return _createMapWidget(context, asyncSnapshot.data);
},
);
...
}
class Page3Widget extends StatelessWidget {
...
@override
Widget build(BuildContext context) => StreamBuilder<LatLng>(
stream: ExampleClass.locationStream,
builder: (context, asyncSnapshot) {
//do something
},
);
...
}
Skyost
Me My IRL name is Hugo Delaunay (it's been more than ten years now that I'm using "Skyost" on the internet) and I'm an amateur developer. My skills It's been some years now that I develop computer programs. I'm also developing some apps for Android and iOS devices. I'm sometimes working on web applications. My projects You will find below two personal projects that I really want to share with you. Mobile Werewolf : Mobile Werewolf is an unofficial mobile version of the famous board game Mafia. The concept is simple : you and your friends are the inhabitants of a strange village where some of you turn into nasty werewolves at night. Bacomathiques : "Bac-o-math-iques" (or just Bacomathiques) is a small app (but also a website) that contains everything you need to revise maths in the french scholar system from the Première to the Terminale ! If you need pass an exam or you just want to revise your lesson : everything is possible and everything is free. If you want to see more projects, feel free to check out my Github profile. Contact me If you have any question feel free to contact me.
Updated on December 07, 2022Comments
-
Skyost over 1 year
I have a simple service which is tracking the current user position :
class LocationService { LatLng _lastLocation; Location location = Location(); StreamController<LatLng> _locationController = StreamController<LatLng>(); Stream<LatLng> get locationStream => _locationController.stream; LocationService() { location.onLocationChanged().listen((locationData) { LatLng location = LatLng(locationData.latitude, locationData.longitude); if(_lastLocation == null || _lastLocation != location) { _lastLocation = location; _locationController.add(location); } }); } }
Then, I'm using this service to create a Map (thanks to flutter_map) which is following the current user position :
class SelfUpdatingMap extends StatelessWidget { final Icon currentPositionIcon; final MapController _controller = MapController(); SelfUpdatingMap({ this.currentPositionIcon, }); @override Widget build(BuildContext context) => StreamBuilder<LatLng>( stream: LocationService().locationStream, builder: (context, asyncSnapshot) { if (asyncSnapshot.hasError || asyncSnapshot.data == null) { return Text('Loading...'); } try { _controller?.move(asyncSnapshot.data, 18); } catch (ignored) {} return _createMapWidget(context, asyncSnapshot.data); }, ); Widget _createMapWidget(BuildContext context, LatLng location) => FlutterMap( options: MapOptions( center: location, zoom: 18, ), layers: [ TileLayerOptions( urlTemplate: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', // https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png is good too. subdomains: ['a', 'b', 'c'], ), MarkerLayerOptions( markers: [ Marker( width: 40, height: 40, point: location, builder: (contact) => currentPositionIcon, ), ] ), ], mapController: _controller, ); }
Then, I use the
SelfUpdating
widget in two places :- The page 1, ancestor of page 2.
- And in the page 3, successor of page 2.
So here is the situation :
- I launch my app, I'm on the page 1. I have my
SelfUpdatingMap
. - I call
Navigator.pushNamed(context, '/page-2')
. - I call
Navigator.pushNamed(context, '/page-3')
. I have anotherSelfUpdatingMap
. - I call two times
Navigator.pop(context)
, I get the page 1 BUT theSelfUpdatingMap
doesn't update itself anymore.
The builder is not even called anymore. So please, what is wrong with this code ?
Thank you !
-
pskink almost 5 yearstry extending
StatefulWidget
and init yourLocationService
insideinitState
method, also try to overridedeactivate
/dispose
to release the resources you init in your customState
-
Skyost almost 5 years@pskink That's what I used to do before using a
StreamBuilder
. Sadly, it's the same result.