skip to Main Content

Building an app with Flutter and Riverpod, using a lot of:

ref.watch(someProvider).when(data: (someData){
   // render layout with data
}, error: (err, stack) { 
  // do stuff with error
}, loading: (){
  return LoadingScreen(); <----
})

The problem is that in most cases the loading screen only renders for a split second, causing a bad experience where the app feels a little "jumpy". I would like to be able to set a minimum of say 2 seconds for the loading state, is it possible to force a widget to stay rendered for a minimum amount of time some how?

2

Answers


  1. I have 2 suggestions for you :

    Option A – You can put a delay of say 2 seconds in your provider, somewhere between loading and the next state. This way you make the loading screen visible at least 2 seconds.

    Option B – You can also make a loadingScreen as an overlay Widget, which dismisses itself after say 2 seconds. This way you make the loading screen visible exactly 2 seconds.

    I believe either way is fine in your case, since you say it flashes, I assume no heavy/long tasks are done in between states. In case you do need heavy/long tasks, option A guarantees the tasks are finished before loading screen disappears.

    Login or Signup to reply.
  2. You can create Stopwatch to track (approximate) operation duration. This example will give you some idea.

    final someProvider = FutureProvider<int>((ref) async {
      final operationDuration = Duration(seconds: 1); //random, you can give it random to test
      final stopwatch = Stopwatch()..start();
      final data = await Future.delayed(operationDuration);
    
      final minOperationTime = const Duration(seconds: 2);
      final extraWaiting = minOperationTime.inMilliseconds - stopwatch.elapsed.inMilliseconds;
      if (stopwatch.elapsed.inSeconds < 2) {
        await Future.delayed(minOperationTime - stopwatch.elapsed);
      }
      return extraWaiting;
    });
    

    And widget

    class LoadingTestOnFutureBuilder extends ConsumerWidget {
      const LoadingTestOnFutureBuilder({super.key});
    
      @override
      Widget build(BuildContext context, WidgetRef ref) {
        return ref.watch(someProvider).when(data: (someData) {
          return Text("got data  ${someData}");
        }, error: (err, stack) {
          return Text("Err");
        }, loading: () {
          return CircularProgressIndicator();
        });
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search