The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
To-Do App With Flutter: Step By Step Guide
1. To-Do App With Flutter: Step By Step
Guide
Flutter is easy to learn and implement compared to other
programming languages. Due to its features like single
code-base, support for multiple platforms, etc., Flutter stands
out. Going further, let’s see how to build a step by step guide
to develop a ToDo App using Flutter and why you should hire
Flutter app developer.
Pre-requisites:
Have knowledge of object oriented programming languages
like Dart, Flutter, Java, etc.
Let’s get started:
Things Needed:
Here, we have used Flutter SDK and Android Studio for an
editor. Refer this guide for Flutter installation and Android
Studio setup.
Create an Application:
Create a New Project:
2. Step 1: In the IDE, click on the welcome window or File → New
→ Project → New Project from the main IDE window.
Step 2: Select Flutter in the menu, and click Next.
Step 3: Enter your Project name and Project location.
Step 4: If you are going to publish this app, set the company
domain.
Step 5: Click Finish.
Your newly created project will be the flutter default app.
Data Structure:
Now the first step is to create the data structure as we will
define which data structure is going to be used to store the
TODO list tasks.
Here, we will develop a class to hold the information about the
task to do so, create a file named task.dart in /lib and write the
following code:
class Task {
3. /
/ Class properties
Int _id;
String _name;
bool _completed;
/
/ Default constructor
Task(this._name);
/
/ Getter and setter for id getId() => this._id;
setId(id) => this._id = id;
/
/ Getter and setter for name
getName() => this._name;
setName(name) => this._name = name;
/
/ Getter and setter for completed
isCompleted() => this._completed;
setCompleted(completed) => this._completed = completed;
}
4. Display Tasks:
Now to display the tasks delete all the existing code from
main.dart file and replace it with the following:
The first step is to create a list of tasks. To do so write the
following code:
class TODOApp extends StatelessWidget {
/
/ Creating a list of tasks with some dummy values
final List< Task > tasks = [
Task('Do homework'),
Task('Laundry'),
Task('Finish this draft document’)
];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TODO app',
5. home: Scaffold(
appBar: AppBar(
title: Text('TODO app'),
),
/
/ Using ListView.builder to render a list of tasks
body: ListView.builder(
/
/ How many items to render
itemCount: tasks.length,
/
/ Functions that accepts an index and renders a task
itemBuilder: (context, index) {
return ListTile(
title: Text(tasks[index].getName()), );})));}}
With the above code we have one screen which will help you
to display tasks. Our next step is to develop a screen which
allows users to create tasks. Write the following code in
main.dart file:
6. void main() => runApp(TODOApp());
class TODOApp extends StatelessWidget {
final List< Task > tasks = [
Task('Do homework'),
Task('Laundry'),
Task('Finish this tutorial')
];
@override
Widget build(BuildContext context) {
/
/ Instead of rendering content, we define routes for different
screens
/
/ in our app
return MaterialApp(
title: 'TODO app',
initialRoute: '/',
routes: {
7. /
/ Screen to view tasks
'/': (context) => TODOList(tasks: tasks),
/
/ Screen to create tasks
'/create': (context) => TODOCreate(),
},
);
}
}
/
/ A new widget that will render the screen to view tasks
class TODOList extends StatelessWidget {
final List< Task > tasks;
/
/ Receiving tasks from parent widget
TODOList({@required this.tasks});
@override
Widget build(BuildContext context) {
8. return Scaffold(
appBar: AppBar(
title: Text('TODO app'),
),
body: ListView.builder(
itemCount: tasks.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(tasks[index].getName()),
);
}),
/
/ Add a button to open the screen to create a new task
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(context, '/create'),
child: Icon(Icons.add)
9. ),
);
}
}
/
/ A new widget to render new task creation screen
class TODOCreate extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Create a task')),
/
/ We will finish it later
body: Center(child: Text('Not yet')));
}
}
10. The TODOCreate class will hold the form to create tasks.
Whereas, in TODOApp class we defined routes and initialRoute
which will handle navigation logic.
Protip: Use Navigator class to navigate between routes.
To create new tasks we will create a button in the TODOList
class. Next up, on its onPressed event we will call
Navigator.pushNamed to navigate via TODOCreate. Now your
application will look like this:
11. Stateful Components:
To create and edit new tasks we will use stateful components.
Stateful components hold the tasks and notifies the widgets
when it updates. Rewrite the TODO class code as follows:
class TODOApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TODO();
}}
/
/ Here we are defining a StatefulWidget
class TODO extends StatefulWidget {
/
/ Every stateful widget must override createState
@override
State< StatefulWidget > createState() {
return TODOState();
}}
12. /
/ This is the state for then TODO widget
class TODOState extends State< TODO > {
/
/ We define the properties for the widget in its state
final List< Task > tasks = [
Task('Do homework'),
Task('Laundry'),
Task('Finish this tutorial')
];
/
/ Now state is responsible for building the widget
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TODO app',
initialRoute: '/',
routes: {
13. '/': (context) => TODOList(tasks: tasks),
'/create': (context) => TODOCreate(),
}, );}}
Next step is to create a tasks:
Creating Tasks:
Herein, TODOState will provide a callback which you will use
in TODOCreate to create a new task. Callback function passes
into another function so you can execute it later. Rewrite the
code in main.dart:
class TODO extends StatefulWidget {
@override
State< StatefulWidget > createState() {
return TODOState();
}}
class TODOState extends State< TODO > {
/
/ At this point we can remove the dummy data
14. final List< Task > tasks = [];
/
/ Function that modifies the state when a new task is created
void onTaskCreated(String name) {
/
/ All state modifications have to be wrapped in setState
/
/ This way Flutter knows that something has changed
setState(() {
tasks.add(Task(name));
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TODO app',
initialRoute: '/',
routes: {
15. '/': (context) => TODOList(tasks: tasks),
/
/ Passing our function as a callback
'/create': (context) => TODOCreate(onCreate: onTaskCreated,),
},);}}
class TODOList extends StatelessWidget {
final List< Task > tasks;
TODOList({@required this.tasks});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TODO app'),
),
body: ListView.builder(
itemCount: tasks.length,
17. final TextEditingController controller = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Create a task')),
body: Center(
child: Padding(
padding: EdgeInsets.all(16),
child: TextField(
autofocus: true,
controller: controller,
decoration: InputDecoration(
labelText: 'Enter name for your task'
) ))),
floatingActionButton: FloatingActionButton(
18. child: Icon(Icons.done),
onPressed: () {
widget.onCreate(controller.text);
Navigator.pop(context);
},), );}}
Compete Tasks:
Make some changes to the TODOState and TODOList classes.
Write the following code:
class TODOState extends State< TODO > {
final List< Task > tasks = [];
void onTaskCreated(String name) {
setState(() {
tasks.add(Task(name));
});
}
21. itemBuilder: (context, index) {
return CheckboxListTile(
title: Text(tasks[index].getName()),
value: tasks[index].isCompleted(),
onChanged: (_) => onToggle(tasks[index]),
);
}),
floatingActionButton: FloatingActionButton(
onPressed: () => Navigator.pushNamed(context, '/create'),
child: Icon(Icons.add)
),
);
}
}
Now your app should look like this:
22. Adding Firebase:
Create a new project on the Firebase console. Read the
detailed guide here to know how to develop a project. Now
configure your app using Firebase. Follow the following steps
to do so:
1) Open file < project folder >/android/build.gradle
Add the following line in dependencies:
classpath 'com.google.gms:google-services:4.3.3'
23. Make sure that you have google() in all the projects like
allprojects → repositories. Next step is open the file < project
folder >/android/app/build.gradle and add this line to the
bottom of the file:
apply plugin: 'com.google.gms.google-services'
Next up you need to add Firebase plugins in the Flutter, to do
so, < project folder >/pubspec.yaml and edit the folder in the
following way:
Dependencies:
Flutter:
sdk: flutter
# Add these lines:
firebase_core: ^1.4.0
firebase_auth: ^3.0.1
cloud_firestore: ^2.4.0
Install Flutter packages using command line or press Packages
in the Android Studio:
24. Splitting Screen in Separate File:
Currently we have all the screens and widgets in the same file
i.e. main.dart. So, we we will split it into two files; list.dart and
create.dart and add the following code respective files:
class TODOList extends StatelessWidget {
final List< Task > tasks;
final onToggle;
TODOList({@required this.tasks, @required this.onToggle});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TODO app'),
),
body: ListView.builder(
itemCount: tasks.length,
30. );
}
}
Add a Login Screen
To develop a Login screen there are three things we need to
follow:
● Add login screen
● Setup authentication of Firebase console
● Integrate login screen and Firebase API
Start with creating a login.dart file and define the TODOLogin
widget and add it into the routes in main.dart.
Now, add the following code in login.dart file:
class TODOLogin extends StatefulWidget {
/
/ Callback function that will be called on pressing the login
button
final onLogin;
35. }}
class TODOState extends State< TODO > {
final List< Task > tasks = [];
void onTaskCreated(String name) {
setState(() {
tasks.add(Task(name)); });}
void onTaskToggled(Task task) {
setState(() {
task.setCompleted(!task.isCompleted());
}); }
void onLogin(String email, String password) {
/
/ We will finish it later
}
@override
Widget build(BuildContext context) {
36. return MaterialApp(
title: 'TODO app',
initialRoute: '/',
routes: {
'/': (context) => TODOLogin(onLogin: onLogin),
'/list': (context) => TODOList(tasks: tasks, onToggle:
onTaskToggled),
'/create': (context) => TODOCreate(onCreate: onTaskCreated,),
}, ); }}
Now when a user logins it will send email and password to
root widget via callback. Your login screen will look something
like this:
Authenticate with Firebase:
To authenticate we will create a new class of Authentication in
auth.dart it will communicate with Firebase. TODOLogin will
call it on the login button, pass the user to TODOState and
move to the next page.
37. Write the following code in auth.dart file:
class Authentication {
final _firebaseAuth = FirebaseAuth.instance;
Future< FirebaseUser > login(String email, String password)
async {
try {
AuthResult result = await
_firebaseAuth.signInWithEmailAndPassword(
email: email,
password: password
);
return result.user;
} catch (e) {
return null; } }}
void main() => runApp(TODOApp());
class TODOApp extends StatelessWidget {
38. @override
Widget build(BuildContext context) {
return TODO();
}}
class TODO extends StatefulWidget {
@override
State< StatefulWidget > createState() {
return TODOState();
}}
class TODOState extends State< TODO > {
final List< Task > tasks = [];
final Authentication auth = new Authentication();
FirebaseUser user;
void onTaskCreated(String name) {
setState(() {
50. }, ); }}
Setup with Authentication in Firebase Console:
To enable authentication of your application:
● Go to Firebase console → select your project → open
Authentication → click on Setup sign-in method.
● In the next screen, select email/ password and enable it.
Save Tasks to Firebase Firestore:
Turn on Firestore in the Firebase Console. Open it→ go to
database tab → create database → select start in testing mode.
We need to change TODOList to fetch data from Firestore and
update it if user completes the task:
class TODOList extends StatelessWidget {
final collection = Firestore.instance.collection('tasks');
@override
Widget build(BuildContext context) {
return Scaffold(
55. class TODO extends StatefulWidget {
@override
State< StatefulWidget > createState() {
return TODOState();
}}
class TODOState extends State< TODO > {
final Authentication auth = new Authentication();
FirebaseUser user;
void onLogin(FirebaseUser user) {
setState(() {
this.user = user;
}); }
@override
Widget build(BuildContext context) {
return MaterialApp(
56. title: 'TODO app',
initialRoute: '/',
routes: {
'/': (context) => TODOLogin(onLogin: onLogin),
'/list': (context) => TODOList(),
'/create': (context) => TODOCreate(),
}, ); }}
Voila! Our TODO app is ready. Follow these steps to build your
first TODO app using Flutter. Apart from this, if you have an
application idea using Flutter, reach out to us. Hire flutter app
developers from us and our team will help you with turning
your ideas into a reality.