Reputation: 548
I've writen some code that provides a ApiService
to a StateNotifier
. The ApiService
has a dependency on a authenticatorclient
- The auth client has to be created asynchronously as it uses sharedprefs to get a token.
Im just trying to figure out if theirs a more elegant way to how I've written this. Basically when the service apiService is injected into the StateNotifier it could be nullable... That to me is a bit of a code smell.
So in brief this is what im doing...
use a FutureProvider
to Instantiate the RestClient
with a Dio
authenticatorClient = FutureProvider<RestClient>((ref) async {
final prefs = await SharedPreferences.getInstance();
final dio = Dio();
...
return RestClient(dio);
}
And then I watch that and use a MaybeWhen to return the service
final clientCreatorWatchProvider = Provider<ApiService?>((ref) => ref
.watch(authenticatorClient)
.whenData((value) => ApiService(value))
.maybeWhen(
data: (service) => service,
orElse: () => null,
));
So the bit I dont like is the orElse returning null
And then my StateNotifier
is watching...
final AppState = StateNotifierProvider<AppNotifier, String>(
(ref) => AppNotifier(ref.watch(clientCreatorWatchProvider)));
class AppNotifier extends StateNotifier<String> {
final ApiService? apiService;
AppNotifier(this.apiService) : super("loading") {
init();
}
...
}
Any thoughts on the above approach?
Thanks
Upvotes: 6
Views: 3194
Reputation: 5970
One way to solve this problem is to initialize SharedPreferences
outside of a provider. You can then use ProviderScope
to override a synchronous provider, eliminating the need to work with AsyncValue
.
When you initialize your app, do the following:
final sharedPreferences = Provider<SharedPreferences>((_) => throw UnimplementedError());
Future<void> main() async {
final sharedPrefs = await SharedPreferences.getInstance();
runApp(
ProviderScope(
overrides: [
sharedPreferences.overrideWithValue(sharedPrefs),
],
child: MyApp(),
),
);
}
Now you could write your providers like so:
final authenticatorClient = Provider<RestClient>((ref) {
final prefs = ref.watch(sharedPreferences);
final dio = Dio();
...
return RestClient(dio);
}
final clientCreatorWatchProvider = Provider<ApiService>((ref) {
final authClient = ref.watch(authenticatorClient);
return ApiService(authClient);
});
Upvotes: 24