how to make more than one asynchronous calls when open a page using Riverpod?

Viewed 613

when the user of my app open the Home page, I need to make two asynchronous calls to the server

first, I need to get current user data. and then based on the current user data, I need fetch his favorite restaurants.

I have two separate methods to get those data from server

class MyAPI {

   Future<User> getUserData() async {}

   Future<List<Restaurant>> getUserData() async {}

}

then how do I construct those 2 asynchronous methods in my HomePage using Riverpod?

  1. show circular loading indicator
  2. make those 2 asynchronous calls
  3. hide circular loading indicator and load lisView

I know about FutureProvider from Riverpod, but FutureProvider is only for one asynchronous service right?

do I need to somehow combine those two into a single method first and then use FutureBuilder? or is it another way that more common to use? I am not sure

how to solve this issue. sorry I am a beginner in Flutter

1 Answers

This look like a use case of a stateNotifier: first in your data model define a UserData class :

class UserData{
  final User user;
  final List<Restaurant> restaurants;
  UserData(this.user, this.restaurants)
}

next define a state and it's associated stateNotifierProvider :

final userDataProvider = StateNotifierProvider<UserDataNotifier, AsyncValue<UserData>>((ref) => UserDataNotifier());
class UserDataNotifier extends StateNotifier<AsyncValue<UserData>> {
  UserDataNotifier() : super(AsyncValue.loading()){
    init();
  }
  final _api = MyAPI();
  void init() async {
    state = AsyncValue.loading();
    try {
      final user = await _api.getUser;
      final List<Restaurant> restaurants = await _api.getFavoriteRestaurant(user);
      state = AsyncValue.data(UserData(user,restaurants));
    } catch (e) {
      state = AsyncValue.error(e);
    }
  }
}

finally in you UI use a consumer :

Consumer(builder: (context, watch, child) {
  return watch(userDataProvider).when(
      loading: ()=> CircularProgressIndicator(),
      error: (error,_) =>
            Center(child: Text(error.toString())),
      data: (data) => Center(child: Text(data.toString())));
})
Related