Routing in Flutter using Fluro

Amruth Pillai
Flutter Community
Published in
7 min readJun 2, 2019

Routing or navigating from one page to another page is essential to any application, and when I was learning Flutter or be it any framework for the first time, I always faced the issue of jumping from one routing mechanism to another. If only all routing solutions were as simple as a <a href=””> tag.

Nevertheless, when it came to Flutter’s in-built routing mechanism, it was pretty easy to grasp, after a long tutorial and multiple usages in projects, but then came Fluro, and I was amazed. If you come from a front-end web development background, you would feel right at home with the way Fluro handles it’s routes.

The routing technique is fairly simple to understand, but it didn’t have reasonable documentation anywhere, even on their official GitHub project page, so that’s why I’m writing this tutorial :) Hope it helps you!

Anyway, talk is cheap. Let’s get down to code.

What are we building today?

To start learning something, it’s important for us to know what we’re going to be building. This could be helpful for motivation, or even if you’re just passing by finding a solution to your problem, you could jump ahead to see if this is something that would be of use to you.

So, this is the app we’re going to be building today:

As you can see, it’s a simple two page app (Login and Home) with each of them having their own Floating Action Buttons to navigate to the other page.

When moving from Login to Home, we require some extra information, such as username, so we pass that as part of the route parameters. So we’ll be learning how to do that through Fluro.

Let’s start coding!

Flutter is one of the easiest frameworks for anyone to pick up and learn. All you need is a bit of interest and some patience.

I’m going to assume you have Flutter installed on your PC/Mac and have at least the Android SDK or XCode Libraries along with it. If you want to start from scratch, you might want to visit this page:
https://flutter.dev/docs/get-started/install

Let’s start creating our Flutter app. My preferred choice is to use the Terminal, but you could use any IDE to do it for you.

> flutter create fluro_tutorial

Your result should look something like this. Don’t worry if all of them are not ticked green, the only one that matters is the first checkbox.

Let’s go into our project directory and open it up in an IDE of choice. I prefer to use VS Code (cause it’s awesome!), but you could use Android Studio too.

First things first, let’s get the latest version of Fluro. Visit this link and grab the version number right next to the heading: https://pub.dev/packages/fluro. As of the time of writing this tutorial, the latest version is 1.4.0, so we’re going to use that.

Now, go to pubspec.yaml and add the fluro package in your dependencies. The ^ (caret) symbol before the version number indicates that it can be upgraded if a new version arrives.

...
cupertino_icons: ^0.1.2
fluro: ^1.4.0
...

Run the following command once the line has been added so that it would grab the required packages from the internet. If you have a really cool IDE, then it would probably do this step for you, but in case it doesn’t, just run this command on the terminal:

> flutter packages get

Let’s clear up whatever was in our lib/main.dart file, and put in a very simple component that displays one of our pages.

import 'package:flutter/material.dart';

import 'package:fluro_tutorial/pages/login.dart';

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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fluro Tutorial',
home: LoginPage(),
);
}
}

Now for the real deal…

I know, that was a lot. If you’re someone who’s intermediary at Flutter, you might have felt it was a bit too much for just a few couple of steps, but in case someone who is learning Flutter for the first time is glancing upon this article, I didn’t want to undermine any step.

But from here on it, it would be straight-forward and more about the code.
I promise. ✌️

Let’s create two files under a directory called ‘pages’, cause it’s good to stay organised.

lib/pages/login.dart

import 'package:flutter/material.dart';

class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Center(
child: Text('Please Login'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.exit_to_app),
onPressed: () {},
),
);
}
}

lib/pages/home.dart

import 'package:flutter/material.dart';class HomePage extends StatelessWidget {
final String username;
HomePage({this.username}); @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Text('Welcome home, $username!'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.settings_backup_restore),
onPressed: () {},
),
);
}
}

Right now, we have no way to go to our HomePage. Technically, we would want the floatingActionButton on the Login Page to go to the Home Page, and vice versa. We’ll start implementing that right now.

To summarize what we’ve done until now:
1. Created a new Flutter Project
2. Added fluro package to pubspec.yaml
3. Updated main.dart with a simple MaterialApp
4. Created two pages (stateless widgets), LoginPage & HomePage

Now, let’s create a router.dart file inside the lib folder:

lib/router.dart

import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:fluro_tutorial/pages/home.dart';
import 'package:fluro_tutorial/pages/login.dart';
class FluroRouter {
static Router router = Router();
static Handler _loginHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) => LoginPage()); static Handler _homeHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) => HomePage(username: params['username'][0])); static void setupRouter() {
router.define(
'login',
handler: _loginHandler,
);
router.define(
'home/:username',
handler: _homeHandler,
);
}
}

The first line inside the FluroRouter class initializes a static instance of Router() from the Fluro library.

static Router router = Router();

Next, we have a handler where we take care of pointing to which widget/component has to be loaded when visiting a route. You can think of them as controllers if you are coming with knowledge from a previous framework.

// Handler for Login Page
static Handler _loginHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) => LoginPage());
// Handler for Home Page
static Handler _homeHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) => HomePage(username: params['username'][0]));

params[‘username’][0] will return the username sent by the route path, and will be sent to the HomePage as an attribute.

Next, we have a setupRouter() function, where we will define individual routes and their paths. This is also where we will define any parameters if any. Let’s take a close look at the router.define() function.

router.define(
'login', // This is the path
handler: _loginHandler, // This is it's corresponding handler
);
router.define(
'home/:username', // username is a named parameter
handler: _homeHandler,
);

Now, let’s go back to our main.dart file and update the MaterialApp to let it know that we’re using our new uber-cool Router.

lib/main.dart

import 'package:fluro_tutorial/router.dart';
import 'package:flutter/material.dart';
void main() {
// Add this here to initialize the routes
FluroRouter.setupRouter();

runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fluro Tutorial',
// Initial Page set to Login Page
initialRoute: 'login',
// Use the generator provided by Fluro package
onGenerateRoute: FluroRouter.router.generator
);
}
}

Now, on your pages, all you need to do is use the Navigator object to push pages over the stack. Let’s do that now.

lib/pages/login.dart

import 'package:flutter/material.dart';class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Center(
child: Text('Please Login'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.exit_to_app),
onPressed: () {
var username = 'AmruthPillai';
Navigator.pushReplacementNamed(context, 'home/$username');
},

),
);
}
}

Navigator.pushReplacementNamed() is a function that replaces the stack with whatever route you pass to it, so that the user cannot go back to the previous screen by simply pressing the back button. If in case you would want such a functionality of going back a screen, you can use Navigator.pushNamed() with the same attributes.

On the Home Page, it’s fairly simple as we don’t have to pass any parameters as such, so we just have to call pushReplacementNamed() again.

lib/pages/home.dart

import 'package:flutter/material.dart';class HomePage extends StatelessWidget {
final String username;

HomePage(this.username);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: Text('Welcome home, $username!'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.settings_backup_restore),
onPressed: () {
Navigator.pushReplacementNamed(context, 'login');
},

),
);
}
}

And that’s it!

Did you know that you can click on the clap button on Medium upto 50 times? If you really appreciated the tutorial, the time put into working on it and thought it was useful, please tap on the clap button as much as you can. It would motivate me to write a lot more articles like these in the future.

Hey there, I’m Amruth Pillai, you can read more about me and what I do on my website. I am fairly new to Flutter and I’m learning on the go, so wanted to give back to the community as much as I have learned from it. If you find any issues in the article, please do let me know in the comments below.

--

--

Amruth Pillai
Flutter Community

I am yet another wannabe photographer, graphic designer, writer, developer and VTU engineer. That last one was enough for you to feel sorry for me.