-
Everything working well when the app is either in Foreground or Terminated
-
Flutter: 3.13.9 | GetX: 4.6.6 | get_storage: 2.1.1
My LocalNotificationsController class extends GetxService which as mentioned in the package that the controller will be available during all app life cycle but the issue that i’m facing is that when the app goes to background the it’s no longer available.
In my main file i’m calling initialServies
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await initialServies();
initialServies:
class MyServices extends GetxService {
late GetStorage localStorage;
late FirebaseMessaging firebaseMessaging;
Future<MyServices> init() async {
await GetStorage.init();
localStorage = GetStorage();
firebaseMessaging = FirebaseMessaging.instance;
return this;
}
}
initialServies() async {
await Get.putAsync(() => MyServices().init());
await Get.putAsync(() => NotificationsService().initNotifications());
Get.put(UsersController());
Get.put(LocalWishlistController());
Get.put(LocalNotificationsController());
}
LocalNotificationsController:
class LocalNotificationsController extends GetxService with WidgetsBindingObserver {
MyServices myServices = Get.find();
var notifications = <NotificationModel>[].obs;
@override
void onInit() {
WidgetsBinding.instance.addObserver(this);
fetchNotifications();
super.onInit();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
// fetchNotifications();
}
}
@override
void onClose() {
WidgetsBinding.instance.removeObserver(this);
super.onClose();
}
// fetch notifications from local storage
void fetchNotifications() {
List storedNotificationsList = myServices.localStorage.read('notifications') ?? [];
notifications.value = storedNotificationsList.map((notification) => NotificationModel.fromJson(notification)).toList();
notifications.sort((a, b) => b.createdAt.compareTo(a.createdAt));
}
// Add a new notification for the current user
void addNotification(RemoteMessage message) {
// Check if the notification already exists
if (notifications.any((notification) => notification.id == message.messageId)) {
return;
}
// Add the notification to the list
notifications.insert(
0,
NotificationModel(
id: message.messageId!,
title: message.notification!.title!,
body: message.notification!.body!,
createdAt: Timestamp.now(),
seen: false,
type: message.data['type'] ?? '',
typeId: message.data['id'] ?? '',
),
);
// Save the notification to local storage
List<Map<String, dynamic>> notificationsMap = notifications.map((notification) => notification.toJson()).toList();
myServices.localStorage.write('notifications', notificationsMap);
// fetchNotifications();
}
notifications_service.dart:
Future<void> handleBackgroundMessage(RemoteMessage message) async {
await Firebase.initializeApp();
await Get.putAsync(() => MyServices().init());
final localNotificationsController = Get.put(LocalNotificationsController());
localNotificationsController.addNotification(message);
}
Future<void> handleForegroundMessage(RemoteMessage message) async {
if (message.notification != null) {
Get.find<LocalNotificationsController>().addNotification(message);
await NotificationsService()._showNotification(message);
}
}
class NotificationsService extends GetxService {
The whole story is when receiving a notification while the app is in the background, as you see i’m obliged to use Get.put again since if i don’t do that i got the controller is not found.
So what happens is that it’s like two separated controller are created i noticed that by printing the notification list everywhere, so the notification gets successfully added but i don’t find the old notifications it’s like a new empty list and when i resume the app the list has the old notifications without the new one (same thing about the content of local storage).
And all this happen after noticing that the UI is not getting updated when received a new notification in the background (i’m using GetX builder to listen for changes in the notifications list since it’s observable in the notifications screen)
- I already tried to use Get.put in the main file
- I already tried to use notifications.refresh() and everywhere possible
- I already tried to use update() everywhere possible even that the notifications is RxList which means i don’t need to use update()
- I already tried to use refresh indicator and fetchNotifications
- I already tried to use lazyPut, putAsync
- I already tried to use initialBindings
This seven minute video presents a good detailed description of “why not getx”: youtu.be/zlIgy4es5Ts
have you track where/when exacly the service/controller is deleted?