There's three Flutter packages I am using to implement a functionality whereby a user pulls to refresh, a geo-coordinate is retrieved using BLoC logic and passed back to Flutter.
Trouble is, I cannot get the BLoC to yield the return result when I dispatch a call in pull-to-refresh.
geolocation_bloc.dart
class GeolocationBloc extends Bloc<GeolocationEvent, GeolocationState> {
@override
GeolocationState get initialState => GeolocationUninitialized();
@override
Stream<GeolocationState> mapEventToState(GeolocationEvent event) async* {
if (event is RequestLocation) {
yield* _mapGeolocationRequestLocation();
}
}
Stream<GeolocationState> _mapGeolocationRequestLocation() async* {
Position position;
position = await Geolocator().getCurrentPosition();
print("RETRIEVED LOCATION"); // I CAN REACH HERE EVERYTIME.
if (position == null) {
yield LocationLoaded(0, 0);
} else {
yield LocationLoaded(position.latitude, position.longitude);
}
}
Retrieves a geo-coordinate. If sensor is off/broken, return (0,0) instead.
feed_page.dart
@override
void initState() {
super.initState();
_geolocationBloc.dispatch(RequestLocation());
}
void _onRefresh() {
_geolocationBloc.dispatch(RequestLocation());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Username')),
body: BlocProviderTree(
blocProviders: [
BlocProvider<PostBloc>(bloc: _postBloc),
BlocProvider<GeolocationBloc>(bloc: _geolocationBloc),
],
child: BlocListenerTree(
blocListeners: [
BlocListener<GeolocationEvent, GeolocationState>(
bloc: _geolocationBloc,
listener: (BuildContext context, GeolocationState state) {
if (state is LocationLoaded) {
print('LOADED'); // THIS NEVER GETS PRINTED WHEN PULLED TO REFRESH.
lat = state.latitude;
long = state.longitude;
}
..
The driver class dispatches a request RequestLocation() once in initState() and every time onRefresh() is called.
However, while the first time RequestLocation() is called it is passes successfully i.e. in initState(), subsequent calls using the pull-to-refresh onRefresh() method does not seem to yield the LocationLoaded() state.
log
Restarted application in 2,849ms.
I/flutter ( 6125): AppStarted
I/flutter ( 6125): RequestLocation
I/flutter ( 6125): RETRIEVED LOCATION
I/flutter ( 6125): Transition { currentState: GeolocationUninitialized, event: RequestLocation, nextState: LocationLoaded { latitude: 37.4219983, longitude: -122.084} }
I/flutter ( 6125): LOCATION LOADED
I/flutter ( 6125): RequestLocation
I/flutter ( 6125): RETRIEVED LOCATION
As per the log, the first call prints both RETRIEVED LOCATION and LOCATION LOADED, but nothing else occurs after the second RETRIEVED LOCATION.
How can I fix this such that the pull to refresh will successfully call on the BLoC logic which in turn return a LocationLoaded() object with the appropriate coordinates.
I managed to solve this by removing the Equatable inheritance from my State and Event BLoC classes. Equatable implementation of equality checking resulted in the BlocListener not short-circuiting to the corresponding if/else block:
i.e. if (state is LocationLoaded)..
There is a possibility that the equality check is stricter in Equatable or since I'm passing two coordinates in the state (Latitude/Longitude), it causes the equality check to fail.
State Class:
@immutable
abstract class GeolocationState extends Equatable { // Remove inheritance.
}
class LocationLoaded extends GeolocationState {
}
class GeolocationUninitialized extends GeolocationState {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With