I made a program to show what problem I'm facing with streamBuilders distributed in several pages connected in one single stream. Git here: https://github.com/EuHigorBarbosa/stream_builder_test.git
The mini program was build with 3 pages: A -> B -> C. The problem is when I upgrade the data of stream in page C, the streamBuilder in page C upgrades the data with no problem. But when I pop the page to the page B, the streamBuilder of page B didn't update the data of snapshot and show up the old value. Both streamBuilders are connected with the same stream.
But when I go back to the page A and go forward to page B, the value of B is now update.
My goal is to show the update data to the user, always, in all pages. But I don't understand what I'm doing wrong.
My stream is a MultiStreamController inside a singleton class.
Page A
class PageAA extends StatefulWidget {
const PageAA({Key? key}) : super(key: key);
@override
State<PageAA> createState() => _PageAAState();
}
class _PageAAState extends State<PageAA> {
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Container(
//decoration: BackGroundImage.BackGroundImageBoxDecoration,
child: Scaffold(
appBar: AppBar(title: Text('Page A')),
//backgroundColor: Colors.transparent,
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(child: Text('Start the program in page C', style: TextStyle(color: Colors.black, fontSize: 20))),
IconButton(icon: Icon(Icons.arrow_forward_ios), onPressed: ()=>Navigator.of(context).pushNamed('/pageB'),)
],
),
),
),
);
});
}
}
Page B
class PageBB extends StatefulWidget {
const PageBB({Key? key}) : super(key: key);
@override
State<PageBB> createState() => _PageBBState();
}
class _PageBBState extends State<PageBB> {
SeqDepService seqDepService = SeqDepService();
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Container(
//decoration: BackGroundImage.BackGroundImageBoxDecoration,
child: Scaffold(
appBar: AppBar(title: Text('Page B')),
//backgroundColor: Colors.transparent,
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(child: StreamBuilder<List<SeqDepEntity>>(
stream: seqDepService.activeSeqDepListStream,
builder: ((context, snapshot) {
if(snapshot.hasData){
return (Text('The lenght of last \nSnapshot data is: ${snapshot.data!.length}', style: TextStyle(color: Colors.black, fontSize: 20)));
} else {
return Container();
}
})),),
SizedBox(height: 50,),
Center(child: Text('Enter items on Stream in page C', style: TextStyle(color: Colors.black, fontSize: 15))),
IconButton(icon: Icon(Icons.arrow_forward_ios), onPressed: ()=>Navigator.of(context).pushNamed('/pageC'),)
],
),
),
),
);
});
}
}
Page C
class PageCC extends StatefulWidget {
const PageCC({Key? key}) : super(key: key);
@override
State<PageCC> createState() => _PageCCState();
}
class _PageCCState extends State<PageCC> {
SeqDepService seqDepService = SeqDepService();
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Container(
//decoration: BackGroundImage.BackGroundImageBoxDecoration,
child: Scaffold(
appBar: AppBar(title: Text('Page C')),
//backgroundColor: Colors.transparent,
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
StreamBuilder<List<SeqDepEntity>>(
stream: seqDepService.activeSeqDepListStream,
builder: ((context, snapshot) {
if(snapshot.hasData){
return (Text('The lenght of last \nSnapshot data is: ${snapshot.data!.length}', style: TextStyle(color: Colors.black, fontSize: 20)));
} else {
return Container();
}
})),
Center(child: IconButton(icon: Icon(Icons.add,size: 30, color: Colors.blue,), onPressed: ()=>seqDepService.addActiveSeqDep(SeqDepEntity(id:'unique', content:1)),))
],
),
),
),
);
});
}
}
Stream Class (Abstract and implemented)
abstract class SeqDepService {
List<SeqDepEntity> get activeSeqDepList;
Stream<List<SeqDepEntity>> get activeSeqDepListStream;
/// Add a single item on stream data. The stream data is a List<SeqDepEntity>
addActiveSeqDep( SeqDepEntity entity);
factory SeqDepService() {
return SeqDepServiceFFmpeg();
}
}
(Implemented)
class SeqDepServiceFFmpeg implements SeqDepService {
static SeqDepServiceFFmpeg? _instance;
SeqDepServiceFFmpeg._();
factory SeqDepServiceFFmpeg(){
_instance ??= SeqDepServiceFFmpeg._();
return _instance!;
}
static List<SeqDepEntity> _activeListSeqDep = [];
static MultiStreamController<List<SeqDepEntity>>? _controller;
@override
static final _activeSeqDepStream = Stream<List<SeqDepEntity>>.multi( (controller) {
_controller = controller;
_addInStream(_activeListSeqDep);
}, isBroadcast: true);
@override
List<SeqDepEntity> get activeSeqDepList => _activeListSeqDep;
@override
Stream<List<SeqDepEntity>> get activeSeqDepListStream => _activeSeqDepStream;
@override
void addActiveSeqDep( SeqDepEntity seqDep)async {
_activeListSeqDep.add(seqDep);
_addInStream(_activeListSeqDep);
}
static void _addInStream (List<SeqDepEntity> activeEntities){
dev.log('The number of items on Stream is: ${activeEntities.length}');
_controller?.add(activeEntities);
}
}
The entity SeqDepEntity
class SeqDepEntity {
String id;
int content;
SeqDepEntity({
required this.id,
required this.content,
});
}
I tried to implement the get_it package but it works with the same way...nothing changes. Please, help me...