I'm trying to display a list of documents which works, but I read that one good practice is to manage states (which I'm trying currently to understand too). In this case every time I change of screen using the bottomNavigationBar the streamBuilder executes (I always see the CircularProgressIndicator). I tried call the collection reference in the intState but still the same issue, my code:
class Deparments extends StatefulWidget {
Deparments({Key? key, required this.auth}) : super(key: key);
final AuthBase auth;
@override
_DeparmentsState createState() => _DeparmentsState();
}
class _DeparmentsState extends State<Deparments> {
late final Stream<QuerySnapshot<Object?>> _widget;
Stream<QuerySnapshot<Object?>> getProds(){
CollectionReference ref = FirebaseFirestore.instance.collection("Departamentos");
return ref.snapshots();
}
@override
void initState() {
super.initState();
_widget = getProds();
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: SideMenu(auth: widget.auth),
appBar: AppBar(
title: Text("Departamentos"),
centerTitle: true,
backgroundColor: Colors.green,
),
body: Container(
child: StreamBuilder<QuerySnapshot> (
stream: _widget,
builder: (BuildContext context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
List deparments =
snapshot.data!.docs.map((doc) => doc.id).toList();
return Column(
children: [
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(top: 10),
scrollDirection: Axis.vertical,
itemCount: deparments.length,
itemBuilder: (context, index) {
return SingleChildScrollView(
child: Card(
child: Text(deparments[index]),
),
);
}),
)
],
);
}
}),
),
);
}
}
Update: for those who are facing the same issue Tayan provides a useful solution and he has a video showing the solution https://stackoverflow.com/a/64057210/9429407
CodePudding user response:
Init state will not help you to avoid rebuilds because on changing tabs Flutter rebuilds your Screen. So we need some way to keep our screen alive, so here comes AutomaticKeepAliveClientMixin.
class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin<Home> {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
//Make sure to include the below method
super.build(context);
return SomeWidget();
}
}
The above implementation keeps all of your tab state persists and does not rebuilds the tabs again. Well this may serve your purpose but it may not be idle because this loads all the tabs at once even if the user actually didnt visited a tab, so to avoid the build unless a tab is clicked, use the above method in combination with pageview.
Check out pageView implementation
Also, if you want a better way to manage state and save some of your read calls to Firestore, then you should store data locally and fetch only those needed and/or use paginations.
CodePudding user response:
Initialize your stream in initState
just like this answer: