Reputation: 465
When a user posts a comment. It stores the comment into the database (Mysql) but the streamProvider is not updating the listview for some reason. I'm able to access the provider and the commentData. But when I post a new comment. through add method. As I said, the listview does not display the new comment which has been sent to the database.
class CommentModel {
final int reportId;
final String text;
const CommentModel(this.reportId, this.text);
}
class CommentProvider {
Stream<List<CommentModel>> intStream(int reportId) {
return Stream.fromFuture(getComments(reportId));
}
Future<List<CommentModel>> getComments(int reportId) async {
final comments = await _fetchComments(reportId);
final List<CommentModel> messages = List<CommentModel>();
for (int i = 0; i < comments.length; i++) {
messages.add(CommentModel(reportId, comments[i]["text"])));
}
return messages;
}
Future<void> add(CommentModel data) async {
await _postComment(data.reportId, data.text);
}
}
MultiProvider(
providers: [
ChangeNotifierProvider<CommentProvider>(create: (_) => CommentProvider()),
StreamProvider<List<CommentModel>>(
create: (_) => CommentProvider().intStream(int.tryParse(reportData["id"])),
initialData: null,
),
],
child: CardCommentWidget(
reportId: int.tryParse(reportData["id"]),
),
),
final commentData = Provider.of<List<CommentModel>>(context);
ListView.builder(
key: PageStorageKey("commentsScroll"),
shrinkWrap: true,
itemCount: commentData.length,
itemBuilder: (BuildContext context, int index) {
final comment = commentData[index];
return Text(comment.text);
},
),
Upvotes: 1
Views: 394
Reputation: 5989
Looks like you simply convert the out put of the getComments
method to a stream. Meaning when you call the intStream
method you will get a stream which only emits the results of the getComments
method once. There is nothing letting the stream know that more items are added.
I can't guess what kind of database you are using to back this up and which "streaming" capabilities it has but someone needs to let your stream know that a new item has been added. One way to solve this would be something like this:
StreamController
which will act as stream and sink;intStream
method, initialize the StreamController
with the outcome of the getComments
method and return the stream of the StreamController
;StreamController
.In code this could look something like this:
class CommentProvider {
final StreamController<List<CommentModel>> _streamController;
Stream<List<CommentModel>> intStream(int reportId) {
// Initialize a new instance of the StreamController
// and emit each comment when someone starts listening
// to the stream.
if (_streamController == null) {
_streamController = StreamController<List<CommentModel>>
.broadcast(
onListen: () async => await getComments(reportId),
onErrror: (error) {
// Handle error here...
},
);
}
return _streamController.stream;
}
Future<List<CommentModel>> getComments(int reportId) async {
final comments = await _fetchComments(reportId);
final List<CommentModel> messages = List<CommentModel>();
for (int i = 0; i < comments.length; i++) {
messages.add(CommentModel(reportId, comments[i]["text"])));
}
return messages;
}
Future<void> add(CommentModel data) async {
await _postComment(data.reportId, data.text);
// Emit the updated list containing the added
// comment on the stream.
if (_streamController != null) {
final comments = await getComments(data.reportId);
_streamController?.add(comments);
}
}
}
This above code is an example and should work. You might need to tweak it a little bit as mentioned in the comments that are part of the code example. And like I mentioned some databases directly support streaming (e.g. Firebase) which directly return the result of a query as a stream and will automatically add items to the stream when they are added to the database and match the query criteria. I couldn't deduce this from your code though.
Some reading material on working with the StreamController
class can be found here:
EDIT:
I updated the logic in the add
method to make sure the _streamController
if not null
.
EDIT 2:
Updated the code to return a stream emitting lists of comments, so we can better facilitate the ListView
class.
Upvotes: 1