Last active
April 19, 2024 12:15
-
-
Save frankvollebregt/b1f4ce1b076858319b2f92004451ecbc to your computer and use it in GitHub Desktop.
Flutter route aware StreamBuilder that automatically pauses and resumes as new routes are pushed/popped on the Navigator. Note that some streams might not respect a call to the pause/resume methods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
void main() { | |
// Register the RouteObserver as a navigation observer. | |
// Share it through your state management package like Provider/Bloc/Riverpod | |
// Or define it globally (outside the main function) | |
// and import main.dart in your stream builder file... | |
final routeObserver = RouteObserver<ModalRoute<void>>(); | |
runApp( | |
// Adapt as needed, using another package or MultiProvider | |
Provider.value( | |
value: routeObserver, | |
child: MaterialApp( | |
..., | |
navigatorObservers: [routeObserver], | |
), | |
), | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:flutter/material.dart'; | |
import 'package:provider/provider.dart'; | |
/// An overridden Stream Builder that observes the route and pauses | |
/// automatically when the route is no longer visible. | |
class RouteAwareStreamBuilder<T> extends StreamBuilder<T> { | |
/// Create a new Route Aware stream builder. | |
const RouteAwareStreamBuilder({ | |
required super.stream, | |
required super.builder, | |
super.key, | |
}); | |
@override | |
State<RouteAwareStreamBuilder<T>> createState() => _RouteAwareStreamBuilderState(); | |
} | |
class _RouteAwareStreamBuilderState<T> extends State<RouteAwareStreamBuilder<T>> | |
with RouteAware { | |
late final RouteObserver routeObserver; | |
late final StreamSubscription<T>? subscription; | |
final StreamController<T> controller = StreamController(); | |
@override | |
void initState() { | |
super.initState(); | |
// Use your state management or the global variable | |
// to retrieve the route observer here | |
routeObserver = Provider.of<RouteObserver>(context, listen: false); | |
subscription = widget.stream?.listen(controller.add); | |
} | |
@override | |
void didChangeDependencies() { | |
super.didChangeDependencies(); | |
routeObserver.subscribe(this, ModalRoute.of(context)!); | |
} | |
@override | |
void dispose() { | |
subscription?.cancel(); | |
controller.close(); | |
routeObserver.unsubscribe(this); | |
super.dispose(); | |
} | |
/// When the route is popped back to this one, resume the stream | |
@override | |
void didPopNext() => subscription?.resume(); | |
/// When a new route is pushed over top of this one, pause the stream | |
@override | |
void didPushNext() => subscription?.pause(); | |
@override | |
Widget build(BuildContext context) { | |
return StreamBuilder(stream: controller.stream, builder: widget.builder); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment