I have a Flutter architecture question on the best approach on how to navigate when we depend on the app state.
Let us assume we have a simple app that
login page if user is not logged in. On login the app does more things like track analytics, fetch extra data then needs to show the homepagehome page if the user is logged inIn order to know what to show initially, the app checks the secure storage for a previous token/session.
I will list below the two approaches I am aware of and the pros/cons I think they have.
1 approach listening to bloc state
The app can use a blocprovider and listen to the emited states.
Simple pseudocode example
if (state instanceof LoggedIn) {
return HomePage();
}
return LoginPage();
Pros:
Can be simple to understand
Cons:
If we need to prefetch more data after log-in somehow I see this approach needing to mix business login into the App.dart the presentation layer
2 approach navigating from the bloc
In this approach we can emit one event from the root app like this
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
_appBloc.add(AppOpened());
});
}
Then on AppOpened event the bloc checks session if the user is already logged in, and based on this information redirects to login or home page using a navigatorKey navigatorKey: _navigationBloc.navigatorKey,
pros:
cons:
The bloc pattern will be abused and the bloc will be also doing navigation not just receiving data and reducing a new state
Question
What do you think is the best approach ? Please feel free to suggest other approaches as well. Those 2 are the only ones I am aware at the moment.
You can use a FutureBuilder like:
FutureBuilder(
future: _appState.checkForLoginCredentials(),
builder: (BuildContext context, AsyncSnapshot<List<bool>> snapshot) {
return (snapshot.connectionState == ConnectionState.done)
? _getLauncherScreen(snapshot.data)
: Container();
},
))
which would call a method returning a boolean array like
Future<List<bool>> checkForLoginCredentials() async {
String? authToken = await getAuthToken();
bool? onboarded = await isOnBoarded();
ProfileResponse? profile = await getUserProfile();
var isLoggedIn = authToken != null && authToken.isNotEmpty;
var isProfileComplete = profile != null;
return [
onboarded ?? false,
isLoggedIn,
isProfileComplete
];
}
You can use the values of the array of navigate to different parts of the application like:
//Returns the Starting Screen of Application based on the application journey
//of the User.
Widget _getLauncherScreen(List<bool>? data) {
if (data == null) return Container();
final isOnBoarded = data[0];
final isLoggedIn = data[1];
final isProfileComplete = data[2];
if (!isOnBoarded && !kIsWeb) {
return const OnBoardingScreen();
} else if(!isLoggedIn){
return const LoginBaseScreen();
} else if(!isProfileComplete) {
return const CreateProfileBaseScreen();
} else {
return const ParentBaseScreen();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With