【问题标题】:Awesome_Notifications - Bad state: Stream has already been listened toAwesome_Notifications - 错误状态:流已被收听
【发布时间】:2021-03-22 22:32:03
【问题描述】:

我正在使用这个flutter library 来处理通知。在我的HomeView 中的initState() 中,我初始化了这个监听器:

_notificationsActionStreamSubscription = AwesomeNotifications().actionStream.listen((receivedNotification) {
  print("user tapped on notification " + receivedNotification.id.toString());
});

稍后当有人登录或退出我的应用时,我会调用这些行:

Navigator.of(context).popUntil((route) => route.isFirst);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => HomeView()));

这让我们再次调用我的HomeViewinitState() 导致错误:

Bad state: Stream has already been listened to.

这就是为什么我在从上面调用两条 Navigator 行之前这样做,但没有成功:

AwesomeNotifications().createdSink.close();
_notificationsActionStreamSubscription.cancel();

我做错了什么?我取消了流订阅,为什么我仍然收到此错误消息?

感谢您的建议!

【问题讨论】:

  • 试试 _notificationsActionStreamSubscription.close();

标签: flutter


【解决方案1】:

根据文档,侦听器应该是顶级函数并在 main.dart 文件中实现。 您基本上应该将所有侦听器移动到不同的函数或类,然后在主函数中调用它

void main(){
  WidgetsFlutterBinding.ensureInitialized();
  notificationInit();
  runApp(MaterialApp(home: YourApp()));
}

void notificationInit() async {
  await AwesomeNotifications.initialize(...);
  _notificationsActionStreamSubscription = ...;
  _notificationsCreatedStreamSubscription = ...;
  _notificationsDisplayedStreamSubscription = ...;
  _notificationsDismissedStreamSubscription = ...;
}

【讨论】:

  • 嗨,贝克齐尔。我有几乎完全相同的问题,我按照您的指示进行操作。但是,我在 'of(context)'.showSnackBar .....'' 中的 'context' 处出现以下红色下划线错误。请帮忙....非常感谢。 ~~~ AwesomeNotifications().createdStream.listen((notification) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( 'Notification Created on ${notification.channelKey}', ), )); }); ~~~
  • 这可能是因为您无权访问函数中的任何 BuildContext。您可以为主页创建一个新的全局键并访问 createdStream 侦听器中的上下文。假设您有一个用于主页的有状态小部件,您应该首先在其外部添加这一行 final HomeKey = new GlobalKey<_MyHomePageState>();。然后在 createdStream 监听器中添加这一行BuildContext context = HomeKey.currentContext;。现在错误应该消失了,但我不确定这是否可行,所以请告诉我
  • 当然,您不能从任何页面获取上下文。只取那些已经初始化的。在这种情况下,假设 MyHomePage 是 MaterialApp 小部件的home
【解决方案2】:

你得到的错误不是_notificationsActionStreamSubscription引起的。

如果你仔细阅读它说

流已被收听

这意味着AwesomeNotifications().actionStream 可能一次只能处理一个侦听器。

_notificationsActionStreamSubscription.cancel() 似乎不起作用,AwesomeNotifications().actionStream 可能不知道流侦听器已关闭。

每次推送页面时,都会重新构建它,AwesomeNotifications() 会抛出错误,因为它认为您正在附加第二个侦听器。

所以我提出了这个解决方案:notificationsActionStreamSubscription 移动到HomeView 的父小部件。 在父级中创建实例,然后将其附加到 actionStream。 每次调用Navigator.pushReplacement将其作为参数发送

HomeView:(我将其设为 statefullwidget)

class HomeView extends StatefulWidget {

  final StreamSubscription<ReceivedAction> notificationsActionStreamSubscription;
  const HomeView({Key key, @required this.notificationsActionStreamSubscription}) : super(key: key);
  
  @override
  _HomeViewState createState() => _HomeViewState();
}

class _HomeViewState extends State<HomeView> {

  //You can access with widget.notificationsActionStreamSubscription
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('HomeView '),
      ),
      body: Container(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [],
            )
          ],
        ),
      ),
    );
  }
  
}

在您的父小部件中(我想它是一个有状态的小部件):

  StreamSubscription<ReceivedAction> notificationsActionStreamSubscription;

  @override
  void initState() {
    super.initState();
    notificationsActionStreamSubscription =
        AwesomeNotifications().actionStream.listen((receivedNotification) {
      print(
          "user tapped on notification " + receivedNotification.id.toString());
    });
  }

而且每次推送 HomeView 时:

Navigator.of(context).popUntil((route) => route.isFirst);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => HomeView(notificationsActionStreamSubscription:
                    notificationsActionStreamSubscription)));

通过这样做,notificationsActionStreamSubscription 将不会在您每次推送HomeView 时重新构建并附加到AwesomeNotifications().actionStream

【讨论】:

  • 如何在推送 HomeView 时将notificationsActionStreamSubscription 作为参数?它来自哪里?
  • 由于我不知道您完整的应用程序结构,因此无法准确告诉您。在我的情况下(我试图复制你的代码)我正在从另一个名为 Root 的小部件推送 HomeView,并在 main.xml 中定义。我在那个小部件中定义了 notificationsActionStreamSubscription。
猜你喜欢
  • 2021-12-26
  • 2020-03-08
  • 2021-06-19
  • 2023-02-16
  • 2018-12-26
  • 2019-07-23
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
相关资源
最近更新 更多