未处理的异常:setState() 在 dispose() 之后调用

Unhandled Exception: setState() called after dispose()

我正在尝试使用 Firebase Messaging 在我的 flutter 应用程序中接收通知以在应用程序中显示它们,但我不断收到错误消息:

/FLTFireMsgReceiver( 6823): broadcast received for message
E/flutter ( 6823): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: setState() called after dispose(): _TipsState#aa4df(lifecycle state: defunct, not mounted)
E/flutter ( 6823): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter ( 6823): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter ( 6823): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter ( 6823): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1085:9)
E/flutter ( 6823): #1      State.setState (package:flutter/src/widgets/framework.dart:1120:6)
E/flutter ( 6823): #2      _TipsState.getNotification.<anonymous closure> (package:stock_baba/Screens/Tips.dart:38:9)
E/flutter ( 6823): #3      _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter ( 6823): #4      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter ( 6823): #5      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
E/flutter ( 6823): #6      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
E/flutter ( 6823): #7      _DelayedData.perform (dart:async/stream_impl.dart:591:14)
E/flutter ( 6823): #8      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
E/flutter ( 6823): #9      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:663:7)
E/flutter ( 6823): #10     _rootRun (dart:async/zone.dart:1418:47)
E/flutter ( 6823): #11     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter ( 6823): #12     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter ( 6823): #13     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter ( 6823): #14     _rootRun (dart:async/zone.dart:1426:13)
E/flutter ( 6823): #15     _CustomZone.run (dart:async/zone.dart:1328:19)
E/flutter ( 6823): #16     _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
E/flutter ( 6823): #17     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1276:23)
E/flutter ( 6823): #18     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter ( 6823): #19     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)

PushNotification class 是一个简单的 class,带有字符串字段 title、body、dataTitle 和 dataBody。 我的代码如下:

class _TipsState extends State<Tips> {
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
  final List<PushNotification> messages = [];
  PushNotification? _notificationInfo;

  @override
  void initState() {
    getNotification();
    super.initState();
  }

  void getNotification() async {
    NotificationSettings settings =
        await _firebaseMessaging.requestPermission();

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      print("Permission granted!");

      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        PushNotification notification = PushNotification(
            title: message.notification?.title,
            body: message.notification?.body,
            dataTitle: message.data['title'],
            dataBody: message.data['body']);

        setState(() {
          _notificationInfo = notification;
        });

        if (notification != null) {
          showSimpleNotification(Text(_notificationInfo!.title!),
              duration: Duration(seconds: 2),
              subtitle: Text(_notificationInfo!.body!));
        }
        print(notification);
        print(message.data);
      });
    } else {
      print("Permission declined!");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: messages.isEmpty
          ? Container()
          : ListView(
              children: [Text(messages[0].title!)],
            ),
    );
  }
}

我尝试用 mounted() 包装我的 setState() 但它不起作用。

如何解决此问题并在我的应用程序中显示收到的通知?

处理后取消Stream

创建StreamSubscription变量

  StreamSubscription messagingSubscription;

将变量分配给您的 listen

....
messagingSubscription = FirebaseMessaging.onMessage.listen((RemoteMessage message) {

Dispose 你的 StreamSubscription

  @override
  void dispose() {
    messagingSubscription?.cancel();
    super.dispose();
  }

这是我的代码,它正在运行..复制代码并制作飞镖 class 并粘贴它。你的通知开始工作

使用那里的插件

  firebase_core: ^1.11.0
  firebase_messaging: ^11.2.5
  flutter_local_notifications: ^9.2.0
import 'dart:convert';
import 'dart:math';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:vcare/firebase_options.dart';

class NotificationHelper {
  NotificationDetails get _ongoing {
    const androidChannelSpecifics = AndroidNotificationDetails(
      'customer-channel-id',
      'customer-channel-name',
      importance: Importance.max,
      priority: Priority.high,
      ongoing: false,
      autoCancel: true,
    );
    const iOSChannelSpecifics = IOSNotificationDetails();
    return const NotificationDetails(android: androidChannelSpecifics, iOS: iOSChannelSpecifics);
  }

  // Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  // await initFirebase();
  // }

  configure() async {
    await initFirebase();
    FirebaseMessaging messaging = FirebaseMessaging.instance;
    await requestPermission(messaging);
    final String? token = await messaging.getToken();

    // FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    final notification = await setupLocalNotification();
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      showNotification(
        notification,
        title: message.notification?.title,
        body: message.notification?.body,
        payload: message.data,
        type: _ongoing,
      );
    });

    return token;
  }

  Future<void> requestPermission(FirebaseMessaging messaging) async {
    await messaging.requestPermission(
      alert: true,
      announcement: false,
      badge: true,
      carPlay: false,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );
  }

  Future<void> initFirebase() async {
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
  }

  setupLocalNotification() async {
    const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings(
      'notification_icon',
    );
    final IOSInitializationSettings initializationSettingsIOS = IOSInitializationSettings(
      onDidReceiveLocalNotification: (int id, String? title, String? body, String? payload) {},
    );
    final InitializationSettings initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
    );
    var notification = FlutterLocalNotificationsPlugin();
    await notification.initialize(initializationSettings, onSelectNotification: (_) {});
    return notification;
  }

  showNotification(FlutterLocalNotificationsPlugin notifications,
      {required String? title, required String? body, required NotificationDetails type, required payload}) {
    notifications.show(Random().nextInt(100), title, body, type, payload: json.encode(payload ?? {}));
  }
}

然后在 main.dart 文件中调用这个 class 这里是代码

   WidgetsFlutterBinding.ensureInitialized();
      String? token = await NotificationHelper().configure();
    
     _storeFCMToken(token);

      print("deviceToken $token");

如果您发现任何问题,请告诉我。如果您发现此代码对您有帮助。请将我的回答标记为已接受