Reputation: 229
I am using awesome_notifications as my notification plugin; however, I get the error "Bad state: Stream has already been listened to."
whenever I call notifInitialize() in initState(). This happens every time I hot reload the application from fresh.
@override
void initState() {
notifInitialize();
super.initState();
}
This is how I am writing my function. Is there something wrong with how I set up my listeners?
void notifInitialize() {
notificationIcon = true;
AwesomeNotifications().initialize(
// set the icon to null if you want to use the default app icon
'resource://drawable/app_icon',
[
NotificationChannel(
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: Colors.teal,
importance: NotificationImportance.High,
channelShowBadge: true,
),
NotificationChannel(
channelKey: 'scheduled_channel',
channelName: 'Scheduled Notifications',
channelDescription: 'Scheduled Description',
defaultColor: Colors.teal,
locked: true,
importance: NotificationImportance.High,
),
],
);
AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
if (!isAllowed) {
AwesomeNotifications().requestPermissionToSendNotifications();
}
});
AwesomeNotifications().createdStream.listen((notification) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Notification Created on ${notification.channelKey}',
)));
});
AwesomeNotifications().actionStream.listen((notification) {
if (notification.channelKey == 'basic_channel' && Platform.isIOS) {
AwesomeNotifications().getGlobalBadgeCounter().then((value) {
print(value);
AwesomeNotifications().setGlobalBadgeCounter(value - 1);
print(value);
});
}
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => ValidateService()),
//(route) => route.isFirst);
(route) => false);
});
}```
Upvotes: 0
Views: 2873
Reputation: 1167
I noticed some issues with your code.
dispose()
methodBad state: Stream has already been listened to.
.For the first case, you can use the StreamSubscription
class to save an instance of your subscription to state
to enable you cancel it in your widget's dispose method.
StreamSubscription<ReceivedAction>? _actionStreamSubscription;
@override
void initState() {
super.initState();
...
listen();
...
}
void listen() async {
// You can choose to cancel any exiting subscriptions
await _actionStreamSubscription?.cancel();
// assign the stream subscription
_actionStreamSubscription = AwesomeNotifications().actionStream.listen((message) {
// handle stuff here
});
}
@override
void dispose() async {
Future.delayed(Duration.zero, () async {
await _actionStreamSubscription?.cancel();
});
super.dispose();
}
The above should work if you have a dispose()
method to safely cancel existing subscriptions when the tree rebuilds.
But in a situation where you do not have a dispose()
method, you could use a boolean
field to determine if a subscription to the stream exists.
// somewhere in your code, assign a bool to false
bool subscribedActionStream = false;
// Just before your call to subscribe, check if not already subscribed.
if (!subscribedActionStream) {
AwesomeNotifications().actionStream.listen((message) {
// handle stuff here
});
subscribedActionStream = true;
}
Whichever you decide to use should work fine.
Upvotes: 1