-
-
Notifications
You must be signed in to change notification settings - Fork 70
stream() does not work properly with nested StreamBuilders #44
Comments
Thanks for opening this issue. Please do follow the issue template so that we can reproduce this issue on our end. Update events seem to work on my end. If you could share a minimal code snippet to reproduce this issue, that would be great. |
here is the code of that
|
@akram-95
When the outer You can probably avoid this from happening if you could combine the two This not only solves the problem you are facing, it gets rid of the flash that you experience whenever the parent widget rebuilds! class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
late StreamSubscription _questionsListener;
// Stores the StreamSubscription where the userId is the key of the map
final Map<String, StreamSubscription> _profileSubscriptions = {};
// Stores the profile data of users where the key is their uid
final Map<String, Profile> _profiles = {};
final List<Question> _questions = [];
@override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (context, index) {
final question = _questions[index];
return ListTile(
title: Text(question.title),
subtitle: Text(_profiles[question.authorId].name),
);
});
}
void _loadData() {
_questionsListener =
supabase.from('questions').stream().execute().listen((questions) {
_questions.addAll(Question.fromEvent(questions));
for (final question in questions) {
// Make sure only create the listener if a listener for the user has not been created yet
if (_profileSubscriptions[question['authorId']] == null) {
_profileSubscriptions[question['authorId']] = supabase
.from('IndividualProfile:userId=eq.${question['authorId']}')
.stream()
.execute()
.listen((event) {
final profile = Profile.fromEvent(event);
_profiles[profile.uid] = profile;
setState(() {});
});
}
setState(() {});
}
});
}
@override
void initState() {
_loadData();
super.initState();
}
@override
void dispose() {
_questionsListener.cancel();
for (final profileListener in _profileSubscriptions.values) {
profileListener.cancel();
}
super.dispose();
}
} |
Will dig deeper into this issue and share anything that I find here in the meanwhile! |
@dshukertjr Thank you so much for your support , but unfortunately it doesn't work and I did notice that when I update an array of varchar , it's not empty, it has the value [archa] |
Could you please share your table schema as well as the code you are using to produce the above log? |
@dshukertjr On the table the array stars is empty and when I update it , it becomes an new user Id when I want to listen to that I get [archa] |
When you share your code, it is better to share it as text rather than image. That way other people can just copy and paste! In the first code block, could you share what you are assigning to Also, is the reason why you have |
i used stars and likes as an array for every Question , that's the only reason , i did it always like that using firebase
|
@akram-95 |
@dshukertjr Nice to hear |
@akram-95 |
@dshukertjr Oh yeah |
Realtime seems to close on its own when |
Any updates? |
Hi @elhe26 |
What you can do is: class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
late Stream stream1;
late Stream stream2;
@override
void initState() {
super.initState();
stream1 = DatabaseHelper()
.client
.from("Questions")
.stream()
.order("timestamp")
.execute();
stream2 = DatabaseHelper()
.client
.from("IndividualProfile:userId=eq.${questionsList[index].authorId}")
.stream()
.order("timestamp")
.limit(1)
.execute();
}
@override
void dispose() {
// there isn't such thing as disposing streams. this is handled internally
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (context, index) {
final question = _questions[index];
StreamBuilder<List<Map<String, dynamic>>>(
stream: stream1,
builder: (context, questions) {
if (!questions.hasData) {
return const Center(child: CupertinoActivityIndicator());
}
List<Question> questionsList =
questions.data!.map((e) => Question.fromJson(e)).toList();
return Expanded(
flex: 1,
child: ListView.builder(
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
controller: questionsAnswersController.scrollController,
itemCount: questionsList.length,
itemBuilder: (_, index) {
return StreamBuilder<List<Map<String, dynamic>>>(
stream: stream2,
builder: (context, profile) {
if (!profile.hasData) {
return const Center(child: SizedBox());
}
if (profile.hasError || profile.error != null) {
return const Text("Text");
}
if (profile.data!.isEmpty) {
return Container();
}
final dataProfile = profile.data!.first;
IndividualProfile individualProfile =
IndividualProfile.fromJson(dataProfile);
return widgetCard(
individualProfile, questionsList[index]);
},
);
},
),
);
});
});
}
} Can this be closed? |
Closing as solved! |
Bug report
The Streambuilder doesn't update in real-time , it just do that when I add a new row to the table but when I update a row in the table , it doesn't update
Screenshots
Upload.from.GitHub.for.iOS.MOV
The text was updated successfully, but these errors were encountered: