I have a stream builder in the app's home/root page. This stream builder gets triggered whenever I do a page-navigation elsewhere, which has nothing to do with the stream itself.
My understanding, according to here and here, is when a page is popped/pushed in the navigator, it triggers a rebuild on the app, so the stream builder gets re-attached and so it fires. However this seems inefficient, so is there a way to prevent the stream builder from firing when a page is popped/pushed?
Additionally, according to the logs, when I push a page, the page is built and shown first, then the stream builder gets fired. However the stream builder's widget/page does not show at all, even though clearly the logs/debugger show that the stream builder's widget has been returned. Where did it go? How does it work in the Flutter framework?
Below is the full code and logs. The code uses Firebase auth as a the stream builder.
Code:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AppHomePage(),
);
}
}
class AppHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final FirebaseAuth auth = FirebaseAuth.instance;
return StreamBuilder<FirebaseUser>(
stream: auth.onAuthStateChanged,
builder: (_, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final FirebaseUser user = snapshot.data;
if (user == null) {
debugPrint("User is NULL.");
return SignInPage();
} else {
debugPrint("User exists.");
return MainPage();
}
} else {
debugPrint("In waiting state.");
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
}
class MainPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint("Building main page.");
return Scaffold(
body: Center(
child: Text("Welcome to our app!"),
),
);
}
}
class SignInPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint("Building sign-in page.");
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
color: Colors.blue,
child: Text('Sign In as Anonymous'),
onPressed: () {
debugPrint("Anonymous");
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MainPage()),
);
},
),
FlatButton(
color: Colors.red,
child: Text('Sign In with Google'),
onPressed: () => debugPrint("Google"),
),
],
),
),
);
}
}
Logs, where the 4th line indicates a button is pressed to do a navigator.pop():
I/flutter (22339): In waiting state.
I/flutter (22339): User is NULL.
I/flutter (22339): Building sign-in page.
I/flutter (22339): Anonymous
I/flutter (22339): Building main page.
I/flutter (22339): User is NULL.
I/flutter (22339): Building sign-in page.
See Question&Answers more detail:
os