I am currently using Provider in my Flutter project to manage the authentication state of my mobile app. The model for AuthProvider is as follow:
lib/models/auth_provider.dart
class AuthProvider with ChangeNotifier {
// Some methods and properties are removed for simplicity.
// ...
bool loggedIn;
void allowAccess() {
loggedIn = true;
notifyListeners();
}
void revokeAccess() {
loggedIn = false;
notifyListeners();
}
}
The application uses some services from another class to check the validity of the authentication token.
If the the token is not valid anymore, the method in the service in another class will need to revoke the access:
lib/services/auth_services.dart
import 'package:exampleapp/shared/global_context.dart' as global_context;
class AuthService {
// Some methods and properties are removed for simplicity.
// ...
void checkValidity() {
// ...
if(notValid) {
// Use provider to revoke access
Provider.of<AuthProvider>(
global_context.GlobalContext.globalContext!, listen: false)
.revokeAccess();
}
}
}
To achieve this (since there is no context outside of the widget tree), the app uses a global context to allow the services file to invoke the Provider method: lib/shared/global_context.dart
import 'package:flutter/material.dart';
class GlobalContext {
static BuildContext? globalContext;
}
And add the following line in the build method of the widget that might involves auth state change:
global_context.GlobalContext.globalContext = context;
I read that we're not advised to access Provider outside the widget tree and I don't think using a GlobalContext is the best practice. Is there any other way that I could do this by using Provider?
P/S: I'm still learning Flutter, please comment below if any clarification is needed.
CodePudding user response:
This is a very good and important question obviously there are tons of approaches that we can follow here, you can use a global context but you have to make sure it's always the correct context so whenever you push/pop different routes you have to also sync the context
One easy approach i think would be to add the context to checkValidity() function as a parameter
Also i would recommend checking out stacked state management solution https://pub.dev/packages/stacked its perfect for situations like this.
CodePudding user response:
I'm fairly new to flutter so hopefully i'm not sending you in the completely wrong direction!
I usually use the get_it package, It gives the ability to call Provider without needing to specifiy a particular context.
https://pub.dev/packages/get_it
First I would call setupLocator()
import 'package:get_it/get_it.dart';
GetIt locator = GetIt.instance;
void setupLocator() {
locator
.registerLazySingleton(() => AuthProvider());
}
Then use it like this..
class SomeClass {
final _provider = locator<AuthProvider>();
void someMethod(){
_provider.revokeAccess();
}
}