FirebaseMessaging: необработанное исключение: оператор проверки нуля используется для нулевого значения

Получение ошибки в заголовке, указывающей на строку FirebaseMessaging.onBackgroundMessage(_handleNotificationBackground); в notification_service.dart. Я думал, что операторы проверки нуля — это ? и !, и я не использую ни один из них в этой строке. Почему я получаю эту ошибку? При необходимости могу предоставить дополнительную информацию.

Могу ли я что-нибудь добавить к этому вопросу, чтобы улучшить его? При необходимости могу предоставить дополнительную информацию.

основной.дарт:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

  NotificationService(navigatorKey: navigatorKey);
  
  runApp(MyApp(navigatorKey: navigatorKey,));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.navigatorKey});

  final GlobalKey<NavigatorState> navigatorKey;

  return MultiProvider(
    providers: [
      ...
    ],
    child: MaterialApp(
      navigatorKey: navigatorKey,
      ...
  );
}

уведомление_сервис.dart:

class NotificationService {
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  final GlobalKey<NavigatorState> navigatorKey;

  NotificationService({required this.navigatorKey}) {
    _initialize();
  }

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

    // Set up Firebase Cloud Messaging
    FirebaseMessaging.onBackgroundMessage(_handleNotificationBackground); //ERROR POINTS HERE
    // Initialize the local notifications plugin
    final initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/app_icon');
    final initializationSettingsIOS = IOSInitializationSettings(onDidReceiveLocalNotification: onDidReceiveLocalNotification,);
    final initializationSettings = InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: initializationSettingsIOS,
    );
    await flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onSelectNotification: onSelectNotification,
    );

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      _showNotification(message.data);
    });

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      _handleNotificationResume(message.data);
    });

    }

    Future<void> _handleNotificationBackground(RemoteMessage message) async {
      // Handle notification when app is in the background
      // You can navigate to a specific screen using the payload from the notification
     _handleNotificationResume(message.data);
    }

   Future<void> _handleNotificationResume(Map<String, dynamic> data) async {
     // Handle notification when app is resumed from background
     // You can navigate to a specific screen using the payload from the notification
     final route = data['Screen'];

     _navigateToScreen(route: route);
   }
  ...
}
0
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Из вашего кода prblm может возникнуть из ключа навигатора, вы определили его внутри основной функции, и я предполагаю, что вы не предоставили ключ виджету MaterialApp. Поскольку вы не передали его виджету MaterialApp и все еще пытаетесь получить доступ к его контексту, который имеет значение null, в результате чего Navigator push() выдает нулевую ошибку, поскольку контекст имеет значение null.

Еще одна вещь: после просмотра вашего класса обслуживания вы определили _handleNotificationBackground() внутри класса NotificationService, вы не можете этого сделать, вам нужно определить его вне всего класса и fn, просто определите его над классом NotificationService с аннотацией @ pragma('vm:entry-point') над fn, как показано ниже, и не делайте его закрытым с помощью _.

@pragma('vm:entry-point')
Future<void> handleNotificationBackground(RemoteMessage message) async {
  handleMessage(message);
}

class PushNotificationService {
...
}

И еще одна вещь: определите и объявите навигационную клавишу вне main(), чтобы вы могли просто импортировать ее напрямую, не передавая ее повсюду в параметрах.

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  NotificationService();
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  return MultiProvider(
    providers: [
      ...
    ],
    child: MaterialApp(
      navigatorKey: navigatorKey,
      ...
  );
}

Причина, по которой я советую вам сделать его глобальным, заключается в том, что, поскольку handleNotificationBackground находится за пределами всех областей и является глобальным, это облегчит вам обработку и обновление кода в будущем.

Я изменил свой код, чтобы передать ключ навигации в MaterialApp, но все равно получаю ту же ошибку.

whatwhatwhat 04.04.2024 07:41

Обновите свой код в вопросе и добавьте полный код, включая MaterialApp() и часть, в которой инициируются прослушиватели сообщений, а также добавьте _handleNotificationBackground().

Ultranmus 04.04.2024 09:05

Хорошо, я добавил все это

whatwhatwhat 05.04.2024 03:56

@whatwhatwhat я обновил свой ответ, можете ли вы сделать это и попробовать, если это все еще не работает, добавьте _navigateToScreen(route: route), и я постараюсь предоставить вам полный код после того, как протестирую его сам

Ultranmus 05.04.2024 10:28

Хорошо, похоже, теперь это работает. Хотя я не понимаю, почему. Разве не нормально, когда функции класса определяются внутри него? И еще, зачем нам нужно было добавлять @pragma('vm:entry-point')?

whatwhatwhat 07.04.2024 07:04

@pragma используется для определения точки входа для работы cloud_messaging, поскольку эта функция должна выполняться, когда приложение находится на переднем плане или закрыто. Если вы определите его внутри какого-то другого fn, и у Cloud_messaging нет к нему доступа, как он будет обрабатывать операцию щелчка? Думайте об этом как об использовании общедоступной статики в Java, чтобы jvm мог получить к ней доступ. (Это всего лишь пример, он может быть другим) ., посмотрите это для лучшего объяснения

Ultranmus 07.04.2024 07:45

Другие вопросы по теме