Making a Todo App with Flutter

Gearóid M
Jun 7, 2018 · 10 min read

Flutter is Google’s answer to React Native, allowing developers to create native apps for both Android and iOS. Unlike React Native, which is written in JSX, Flutter apps are written in Google’s Dart language.

Flutter is still in technically in beta, but its tools are quite stable, and provide a smooth development experience.

In this post I’ll explain how to create a simple todo app using Flutter.

Install the tools

These instructions are written for MacOS and Linux. Windows requires some extra prerequisites, so follow the Flutter Windows guide, and then move on to the next section, Create an app.

First, download the Flutter SDK for your platform. For this app, we will create a directory called dev in our home directory, and unzip the Flutter SDK there.

mkdir ~/dev
cd ~/dev
unzip ~/Downloads/

Now we can run Flutter on the command line by running ~/dev/flutter/bin/flutter. That's a bit awkward to type, so let's add this directory to our $PATH to make the command shorter. Add this line at the end of your ~/.bashrc file.

export PATH=~/dev/flutter/bin:$PATH

Then run source ~/.bashrc to ensure that this change takes effect. Now you can run flutter straight from the command line. Once this is set up, we need to check to ensure that we have installed everything else we need for app development, such as Android Studio, Xcode (only on MacOS), and other dependencies. Luckily, Flutter comes with a tool that makes it really easy to check this. Just run:

flutter doctor

This will tell you exactly what needs to be installed so that Flutter will run correctly. Follow the doctor’s instructions, and make sure that everything is set up correctly before moving on to the next step.

Create an app

Flutter offers plugins for several IDEs, including Android Studio and Visual Studio Code. However, for our basic app, we can do everything using the command line and a simple text editor. First, let’s create our app, which we will call flutter_todo.

flutter create flutter_todo

Flutter creates a basic “Hello World”-style app with this command. We can test this right away in an Android emulator. Open up Android Studio, which Flutter Doctor will have helped you set up. Here we want to create an emulator, but Android Studio requires us to have a project first. So, let’s use our newly created Flutter project. Choose Import project (Gradle, Eclipse ADT, etc.), and then choose the folder ~/dev/flutter_todo/android. Once it finishes importing your project, check if there are any errors in the console. If there are, let Android Studio fix them.

Now, we can create our emulator by opening Tools > Android > AVD Manager. Click Create Virtual Device, select Pixel, and click through all the defaults until it is created. Now you will see the new device in your list - double-click to start it. Once the emulator is running, it’s time to run our Flutter app.

cd flutter_todo
flutter run

This app is a bit more interesting than a normal Hello World app, and includes some interactivity. Tap the button in the bottom-right to increase the counter in the middle of the screen.

Flutter’s “Hello World” app

Hot reload

Say that we want to change the text in the title bar of the Hello World app. All of the code is located in lib/main.dart. In this file, find this line:

home: new MyHomePage(title: 'Flutter Demo Home Page'),

and replace it with:

home: new MyHomePage(title: 'Basic Flutter App'),

Save the file, and go back to the command line where you ran flutter run. All you need to do is type r, and this will start the hot reload process. You will notice that in the emulator, the title has changed. Not only that, but if you have tapped the button before, you will notice that the count hasn't reset back to 0. This stateful hot reload is what makes this such a useful feature for development. You can adjust your code and test without being forced back to your app's opening screen every time you make a change.

Flutter’s “Hello World” app with a changed title, and maintained state

Flutter Basics

Material Design

Remove all the existing code in lib/main.dart, and add the following:


Since we have made big changes to the app, this time a hot reload will not work. Instead we need to do a full restart of the app. On the command line, type R -- note it is uppercase, unlike for a hot reload. You will see a simple app with a title bar.

The difference in title bar styling on Android (Pixel 2) vs iOS (iPhone X)

Stateless and Stateful Widgets

To make a stateful widget, we need two classes — one for the widget itself, and a second which creates the state. This setup allows the state to be easily saved, and enables the use of features such as hot reloading.

Why does a stateful widget need two classes?
Imagine that we have a todo list widget which contains five todo items. When we add another one to the list, Flutter updates the screen differently to how you might imagine. You may expect that it simply adds this item to the existing widget. In fact, it creates a whole new widget, and compares it to the old one to determine which changes to make on screen.

Since we create a new widget with every change, we cannot store any state in the widget itself, as it will be lost with the next change. This is why we need a separate State class.

The code below shows our newly stateful app. It is functionally the same as our previous code, but it will now be possible to easily change the contents of the todo list. Replace all the contents of lib/main.dart with the code below, and do a full restart with R.

Modifying State

Let’s take a closer look at how exactly a new todo item gets added:

  • The user taps the + button, calling the onPressed callback, which triggers our function _addTodoItem
  • addTodoItem adds a new string to the _todoItems array
  • Everything inside _addTodoItem is wrapped in a setState call, which tells the app that the todo list has updated
  • TodoList.createState is triggered because the todo list has updated
  • This calls new TodoListState(), whose constructor is build, which builds a whole new widget with the updated list of todo items
  • The app takes this new widget, compares it to the previous one, and adds the new item without changing the other items
The app’s second screen, allowing the user to add a task

User Interaction

Adding a todo item

Once the page is created, we need to tell the app how to use it, and that it should animate in on top of the other screen. Flutter provides a Navigator for us to do this, which uses the concept of a navigation stack, which is common in mobile apps. To add the new screen we push it on to the navigation stack. To remove it, we pop it. We will create a new function called _pushAddTodoScreen which will handle all of this. Then we can change our floatingActionButton's onPressed to call this function.

Replace the existing _addTodoItem and build functions with the code below, and add the new _pushAddTodoScreen function alongside them. Trigger a full restart by pressing R to ensure the autogenerated tasks from last time are removed. Click the + button and add a task, and press the enter key on your keyboard. The screen will close and the task will now be on the list.

Removing todo items

A dialog box asking the user to confirm completion of their task

We will create two new functions to achieve this, _removeTodoItem and _promptRemoveTodoItem. _buildTodoItem will also be modified to handle the user's tap interactions. Take a look at the new code below and see if you can follow how it works. I'll go into detail afterwards.

First, we need functionality to remove a task from our list, which is handled by _removeTodoItem. The best way to reference which item we want to remove is by its index in the _todoItems array. Referencing it by its name would cause problems if there were multiple tasks with the same name. Once we have the item's index, removing it from the array is simple, using Dart's removeAt function. Remember that we need to wrap this in setState so that the list will be re-rendered after the item is removed.

Rather than removing the item immediately when a user taps it, it is much more user-friendly to prompt them first. _promptRemoveTodoItem uses Flutter's AlertDialog component to do this. The constructor for this is similar to the previous ones we have seen, such as Scaffold. It simply accepts a text title, and an array of buttons. The handling of button tapping is handled by onPressed, where we call _removeTodoItem if the correct button is pressed.

Finally, we add an onTap handler to each list item in _buildTodoItem which will show the above prompt. We need the index of the todo item for this handler, so we must also modify _buildTodoList to pass the item's index when it calls _buildTodoItem. Flutter will automatically add Material-style tap animations, which are a nice effect for the user.


The final app

There are several things that could be improved in the app if you wish to continue working with it. For example, the user’s todo items are saved between app launches due to Flutter maintaining state, but this is not a reliable way of keeping user data. Instead the user’s todos could be saved safely on the device using shared_preferences.

To further improve the app you could change the theme, or even add categories for the user’s todos.

Continuing with Flutter

Though Flutter is still in beta (v0.3.2 as of writing), its ecosystem is very mature. You will not find yourself missing any big features or lacking documentation. Major apps such as Google Adwords are already using Flutter in production, so it is worth investigating if you are starting to develop a new app.

The Web Tub

Pushing the web current through hybrid mobile and PWA…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store