Is this how to create a Riverpod Provider, whoose value changes according to time?

532 views Asked by At

I am trying to greet the user based on the time of the day (i.e. Good Morning/Afternoon/Evening), and I am thinking of doing this using Riverpod, so that the message changes without the need of rebuild.

this is my attempt:

greeting_message_provider.dart

abstract class GreetingMessageClient {
  Stream<String> getMessage();
}

class GreetingMessageProvider implements GreetingMessageClient {
  @override
  Stream<String> getMessage() async* {
    while (true) {
      int hour = DateTime.now().hour;
      if (hour < 5) {
        yield 'Good Evening,';
      } else if (hour < 12) {
        yield 'Good Morning,';
      } else if (hour < 17) {
        yield 'Good Afternoon,';
      } else {
        yield 'Good Evening,';
      }

      // to only update the value every one hour
      await Future.delayed(const Duration(hours: 1));
    }
  }
}

home_screen.dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'greeting_message_provider.dart';

final greetingMessageClient = Provider<GreetingMessageClient>(
  (ref) => GreetingMessageProvider(),
);

final greetingMessageProvider = StreamProvider<String>(
  (ref) => ref.watch(greetingMessageClient).getMessage(),
);

class HomeScreen extends ConsumerStatefulWidget {
  const HomeScreen({super.key});

  @override
  ConsumerState<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends ConsumerState<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    final AsyncValue<String> greetingMessage =
        ref.watch(greetingMessageProvider);

    return Scaffold(
      body: Center(
        child: Text(
          greetingMessage
              .when(
                  data: (String msg) => msg,
                  error: (Object e, _) => e,
                  loading: () => 'Hi,')
              .toString(),
        ),
      ),
    );
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'home_screen.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'RiverPod Demo',
      home: HomeScreen(),
    );
  }
}

I studies the Riverpod from there example apps and from ResoCoder's guide. And after that I tried to imitate them.

I am new to Flutter & Riverpod Statemanagement, so wanna ask is this how to do it or not. Also I am skeptical for the use of while(true) function.

1

There are 1 answers

1
Ali Ammar On BEST ANSWER

your method will work just fine, you could also simplify it more using Stream.periodic

final greetMsgStream = StreamProvider<String>((ref) {
  return Stream.periodic(const Duration(hours: 1), (_) {
    int hour = DateTime.now().hour;
    if (hour < 5) {
      return 'Good Evening,';
    } else if (hour < 12) {
      return 'Good Morning,';
    } else if (hour < 17) {
      return 'Good Afternoon,';
    } else {
      return 'Good Evening,';
    }
  });
});