Search code examples
riverpodflutter-local-notification

Call provider before runApp flutter


I having setting up local notifications in my flutter app using flutter_local_notifications.

In the example provided on the page the configurations are done before runApp. But I am defining the local notification plugin as riverpod provider to have easier access to the plugin wherever in my code.

It looks as follows:

@riverpod
Future<void> setupFlutterNotifications(SetupFlutterNotificationsRef ref) async {
  final notificationService = ref.watch(notificationServiceProvider);
  await notificationService.setupFlutterNotifications();
}

@riverpod
Future<bool?> requestNotificationPermissions(
  RequestNotificationPermissionsRef ref,
) async {
  final notificationService = ref.watch(notificationServiceProvider);
  return notificationService.requestPermissions();
}

@Riverpod(keepAlive: true)
NotificationService notificationService(NotificationServiceRef ref) {
  return NotificationService(
      ref, FlutterLocalNotificationsPlugin(), FirebaseMessaging.instance);
}

class NotificationService {
  NotificationService(this.ref, this._flutterLocalNotifications, this._fcm);...

  Future<void> showLocalNotification({
    required String title,
    required String body,
 }) async {
   return _flutterLocalNotifications.show(
     0,
     title,
     body,
     _notificationDetails,
     payload: 'No payload yet!',
 );

}

Now, how do I manage to call the provider before runApp? I want to do something like:

await ref.watch(setupFlutterNotificationsProvider.future);
await ref.watch(requestNotificationPermissionsProvider.future);

Solution

  • You can do asynchronous loading in main:

    Future<void> main() async {
      
      final container = ProviderContainer();
      await container.read(setupFlutterNotificationsProvider.future);
      await container.read(requestNotificationPermissionsProvider.future);
      
      return runApp(
        UncontrolledProviderScope(
          container: container,
          child: const MyApp(),
        ),
      );
    }
    

    And then use requireValue in widgets:

    @override
    Widget build(BuildContext context, WidgetRef ref) {
      final notificationPermissions = ref.watch(requestNotificationPermissionsProvider).requireValue;
    
      return ...;
    }
    

    But I would recommend rethinking your architecture:

    • setupFlutterNotifications should not be a provider
    • notificationServiceProvider - it is better to use NotifierProvider based on a class for this purpose.