Flutter: Home screen chooser

Ioannis Brandt Ioannidis
3 min readFeb 28, 2021

--

This article describes a way to dynamically set your home screen in flutter by using FutureBuilder. This specific story is focused on displaying how to show a login screen only the first time that a user enters the application, but it can give you also insights on how a FutureBuilder works in Flutter.

On the root Widget of your application usually you are setting the home screen of your application like this:

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application


@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Ecocup',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomeScreen(title: "My awesome app"),
);
}

We can extend this functionality by implementing a FutureBuilder that will return the required widget based on a value that will indicate if it is the first time the app is running or not. This is demonstrated below:

First of all, we are going to store on disk a value that will indicate that the user has opened the application for the first time. This can be achieved by using SharedPreferences as follows:

Future<bool> isFirstRun() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
_isFirstTime = (prefs.getBool('isFirstTime') ?? true);
return _isFirstTime;
}

Now we know if the user has opened the application, and we can use this information on the FutureBuilder to determine which widget we need to return (e.g. LoginScreen/SignupScreen if first time, HomeScreen otherwise).

Widget determineLandingScreen(BuildContext context) {
return FutureBuilder(
future: isFirstRun(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if(_isFirstTime == true)
return LoginPage(title: 'Ecocup');
else return HomePage(title: 'Ecocup');
}
else return Container();// or some other widget
},
);
}

The FutureBuilder will run the function isFirstRun() asynchronously, and on the result the builder will build the required widget based on the value we retrieved. At this point the root widget of our application should look like:

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
// This widget is the root of your application


@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Ecocup',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: determineLandingScreen(context),
);
}

The AsyncSnapshot object that is passed on the builder can be on 3 possible states:

  1. new AsyncSnapshot<String>.withData(ConnectionState.none, null): This state indicates that the Future is null, thus, the AsyncSnapshot.data will be set to initialData.
  2. new AsyncSnapshot<String>.withData(ConnectionState.waiting, null): This state indicates that the Future is not null, but is not yet completed. The AsyncSnapshot.data will be set to initialData, unless a Future has been previously completed — in which case the data retrieved previously persists.
  3. new AsyncSnapshot<String>.withData(ConnectionState.done, null):This state indicates that the Future has been completed successfully, and the AsyncSnapshot.data will be set to the value that the Future has returned. In case that the Future has been completed with an error, AsyncSnapshot.hasError will be set to true, and AsyncSnapshot.error will be set to the error object.

--

--

Ioannis Brandt Ioannidis
Ioannis Brandt Ioannidis

Written by Ioannis Brandt Ioannidis

Passionate about Clean Code, Software Architecture, IoT and Cross Platform applications.

No responses yet