Получение ошибки в заголовке, указывающей на строку 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);
}
...
}
Из вашего кода 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() и часть, в которой инициируются прослушиватели сообщений, а также добавьте _handleNotificationBackground().
Хорошо, я добавил все это
@whatwhatwhat я обновил свой ответ, можете ли вы сделать это и попробовать, если это все еще не работает, добавьте _navigateToScreen(route: route), и я постараюсь предоставить вам полный код после того, как протестирую его сам
Хорошо, похоже, теперь это работает. Хотя я не понимаю, почему. Разве не нормально, когда функции класса определяются внутри него? И еще, зачем нам нужно было добавлять @pragma('vm:entry-point')?
@pragma используется для определения точки входа для работы cloud_messaging, поскольку эта функция должна выполняться, когда приложение находится на переднем плане или закрыто. Если вы определите его внутри какого-то другого fn, и у Cloud_messaging нет к нему доступа, как он будет обрабатывать операцию щелчка? Думайте об этом как об использовании общедоступной статики в Java, чтобы jvm мог получить к ней доступ. (Это всего лишь пример, он может быть другим) ., посмотрите это для лучшего объяснения
Я изменил свой код, чтобы передать ключ навигации в MaterialApp, но все равно получаю ту же ошибку.