Skip to content

Instantly share code, notes, and snippets.

@frankvollebregt
Last active April 19, 2024 12:15
Show Gist options
  • Save frankvollebregt/b1f4ce1b076858319b2f92004451ecbc to your computer and use it in GitHub Desktop.
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.
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],
),
),
);
}
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