Create a motivation App using Flutter

Anoob Bava
Flutter Community
Published in
13 min readMar 31, 2020
Photo by Artur Aldyrkhanov on Unsplash

I have been learning the Flutter during my spare time and I was eager to write a blog about an app that I was created during my learning time. Before I started, I would like you to know that I am not an expert in Flutter. I was on the journey there and I would like to know anyone got any better way or any issues.

What we are going to do

We will create a motivation app that is taking the quotes from API and will display those quotes and able to save those in our local database when a user added it as a favorite. Also, the option to remove this from the quote from favorites as well.

As you see in my old blogs, I am a big fan of small chunks, that will keep the reader will foresight what we are going to do here.

Note: This is not a basic flutter tutorial, expected the user has some slight knowledge about the Flutter and Dart programming language.

  1. Create a flutter App.
  2. Fetch the Data from API.
  3. Add some styling to the Quote.
  4. Some refactoring for the code.
  5. Added button for like and share the Quote.
  6. Added option to display notifications(snackbar).
  7. Added option to share the quotes.
  8. Save the Quote to the local database.
  9. Tab wise display.
  10. Option to display Favorites.

Now, we can jump to the workflow,

1. Create a Flutter App.

Need to have the Flutter is installed locally and it is up and running, If not, please visit this link and make sure that everything works fine.

We can create the app using

flutter create motivation_on_the_go

motivation_on_the_go is the name of our app, Flutter will install all the dependencies and will create the app. Initially, it will be a basic one which has some scaffold app which shows the count of the button pressed, we can remove those and started our work.

initial commit link for the changes.

scaffolding changes removed commit link.

Now, the app will have only one screen which is displaying the message,

2. Fetch the Data from API.

Now, what we need is to call the API and display the response. I have researched for so many quotes API and I really like this a lot. This is from favqs. They have an API that will revert the quote of the day, which is exactly what we needed.

Now, what we needed a package that can accept the http request and deliver the response in Flutter. We will use the package called http for this.

Here, we need to split the work into some small chunks for better clarity.

  1. Download and install the http package.
  2. Create a class to accept the data.
  3. Handle the request in Flutter.
  4. Display the data in the UI.

1. Download and install the http package.

This step is quite simple. What we need is to locate the package from pub.dev and add that to pubspec.yaml

2. Create a class to accept the data.

This is the more interesting and confusing part. As we know we got some data from API, and it easily iterates through the JSON will get the value we needed. But it is good to have a class to handle the data from API and we can have a constructor for these out of the box and can multiple data types from the response. for more details, visit this link, they have an example to show why we needed models in the first place. I don't like to reinvent the wheel :D

Quote is my class name and I have quoteText which will have the quote which will be displayed and the quoteAuthor will contains the name of the author. Quote.fromJson will parse the JSON response from the API and return the response.

3. Handle the request in Flutter.

When we sent to request to API, we don’t know the final response. Maybe it is a success or failure. So that will be only known after some time, this kind of logic is Future in Flutter. So we need to handle the asynchronous requests, which can be achieved using the async package. Also, we need to import the model class to the main.dart file.

4. Display the data in the UI.

Now, We need to display the data, to make that work, we need to do add some code for that.

Currently, our main.dart will display a Center widget only, we need to change the class to a stateful widget. The reason for that is we have some changes based on API response.

We need to fetch the quote from the API, to do that, we need to call the API and fetch the response since it is a Future thing, we need to have async for this.

We need to run the API when we first take the app, for that we have a built-in function called initState will do the trick.

we have created Future<Quote> quote for accepting the data from the API since it is an object of Quote class mentioned with <Quote> and it is a Future one mentioned with Future

Now, we have got the API and it is available in our quote variable, but we can’t directly display a value in the variable since it is a Future one. What we need to do is to use functions that are used for displaying Future data that can be used. Here, we will have FutureBuilder for this option.

Using FutureBuilder has multiple benefits, will check the API response has content then display the content, or if it is an error, option to display that error or if it is loading the data, we can display the progress bar in the meantime.

will link the quote as Future and will if it contains any data using snapshot.hasData then display those data using

Text(snapshot.data.quoteText)

Text(snapshot.data.quoteAuthor)

If it is an error, will display using the Text(“${snapshot.error}”)

that's it, we have an output now. It is somewhat ugly, but we have an API interaction and response there, be great for that.

3. Add some styling to the Quote.

Now, we need to add some styling to the quote to be displayed in the UI, for that, we will add an image in the background and some fonts.

Use the Stack widget for the image to be displayed, so our background will have the image.

Also for Fonts, will use the Courgette-Regular

So our final result becomes,

commit link.

We have functionality is completed, now it is time for refactoring the code.

4. Some refactoring for the code.

Currently, all the logic for API handling resides in our main.dart. We Will move all this logic to a separate file called QuoteData() and our main.dart will call this class only.

It is a pretty straight forward thing, there is no logic added for this functionality. I have added the commit link to display the changes.

commit link.

5. Added button for like and share the Quote.

Now, our aim is to share and like the quote we received. To do that, we need to have 2 buttons to handle this. We will use the IconButton widget for this. It will be placed just below our quote displayed.

As you can see in the above code, when clicking on the button, it will display the message accordingly.

We have the icon buttons are there, Now to check whether they are working or not. By looking at the debug tab of our editor.

Awesome, now our buttons are working, Now we can add the functionality to those.

commit link

6. Added option to display notifications(snackbar).

Currently, we don’t have a way to understand the button clicked or not. It will be good if we have an alert or popup for that. Here is the snackbar comes to the picture.

snackbar is essentially an alert notification that will automatically be removed after some time. It is a widget from Flutter, So no rocket science here ;)

We have defined a snackbar for our like button and will have a text, which is handling the content and Scaffold.of(context).showSnackBar(snackBar) will show where we need to display the message for this. The below example will show what will be the output for this.

7. Added option to share the quotes.

We have added the buttons and the snackbar now, it is the time to share our quotes to anyone like via WhatsApp or text message, etc. that will be cool right. This can be achieved by using the package called share.

It is pretty simple, just install the package and import to our class, then call the share class with our data, here in this context our quote text.

import ‘package:share/share.dart’;

Here, on pressing share button, we will call the share package and pass the data, will open the installed apps and prompts us to share the data.

commit link

8. Save the Quote to the local database.

Honestly, I would like to say, this step is taking more time to implement because we need to use some extra logics and it is somewhat similar to our normal CRUD option in the web app.

  1. Install the necessary package for the local database.
  2. Create a helper class to deal with the database functions.
  3. Create the variables to fetch the database.
  4. Create a database connection and a table.
  5. Button for saving the data to the database.
  6. Save the data to the database.

Ya, I know, it is a lot of steps, but believe me, it is worth it :)

I have dropped this work because I don’t really understand how this database thing works, but after some research and Googling, I found the workflow and I am happy with this now.

1. Install the necessary package for the local database.

We will use the package called sqflite for database operations and another package path for finding the absolute path.

commit link

2. Create a helper class to deal with the database.

Our aim is like all the code related to our database operations are in a separate class only. To do that, will create a file in the lib path called database_helper.dart

Also will import the quote model class to this helper file.

3. Create the variables to fetch the database.

We need to create the variables to accept the quote text, author and the database id and database connection. So these variables will have the data to be saved to the database.

I have added the variables for the database name and table name, so we can use the global name in the entire class.

4. Create a database connection and a table.

Now, we have created the class, variables for the database, now we need to create the database connection using these but keep in mind that we need to check if the database already exists then fetch the database or else need to create it. Below are the changes we need to do, don’t worry I will explain.

fetchMyDatabase is the starting of all this, since we are checking for the database connection and it is a Future request and it should work as async process, that’s why we added async after the function. If the _db is empty, we need to create a new connection. Since it is an async option, we need to add the package dart:async

_initializeDb will fetch the path and then open the database for the same.

String path = join(await getDatabasesPath(), DB_NAME);

Now path will have the database path and we will call _createMyTable to create the table if it not exists. It is purely an SQL query to do that.

5. Button for Saving the data to the database.

Currently, we have the data up and ready in from the API in the variable, then we click on the button for saving the quote and we need to call the database to save this data.

We will create an object of Quote class to pass the data we received from API and call a method to save this data.

a. Import the database_helper to our main class quote_data.dart

import ‘./database_helper.dart’;

b. Create a variable for the database_helper to create instance.

var dbHelper;

c. Link our dbHelper to the database_helper class in our initState

d. Create an object of Quote class to send the data to the database.

We created an object to save this data and pass this to the database_helper method saveQuote(q) we need to create this method.

6. Save the data to the database.

Now we have fully functional option to build a database connection and we have passed data to the method called saveQuote(q) to save this data to the database.

Our q variable got the data which is from API, but the keys are different since they are under the Quote class, so we need to change those to our column names which match to the database.

This method will do that for us, so we will have the same column name match to our table column, Now we need to create a method in the database_helper.dart to save the data.

quote.toMap() will do the trick for the conversion.

That will be enough, but we don’t have a way to check whether the data saved or not and we need to have a mechanism to show the saved quotes. To do that will be using a tab wise display to show the current quote and the saved quotes.

9. Tab wise display.

Our aim is to display the current quote in one tab and the right side will have the saved quotes. To do that, will use the tabController widget.

Inside the TabBarView, we have 2 children, one is a stack holds our current quote and other is Center where will have the favorite quotes.

Now, test this to make this work.

Awesome, let’s proceed to display favorite quotes instead of hardcoded text./

10. Option to display Favorites.

What we are going to do is create a stateful class to fetch the data from the database and display those in the UI. It needs to create a method to fetch the data from the database and a FutureBuilder to display data in the tab page as well.

FavoriteQuotes() is not yet to be created, we need to create that.

fetchDatafromTable() is a method which will fetch from database using the method fetchSavedQuotes() which will be defined in database_helper class.

Now what we will do is iterate through the data and display those in the UI using the FutureBuilder()

Some times, we have multiple data there, so we need to display the data in a tile format, for that we need to create a ListView.builder() to display data in a tile format.

We have added a red icon, which will provide an option to remove the data from the table once we clicked on that, We need to create a method deleteQuoteFromFavorite(id) in database_helper.dart class.

Also, we have added a snack bar to notify the user once it is removed or not.

Now, we need to check the added favorites are coming or not.

Awesome, we have one thing remaining which is to test if it is removed or not.

Awesome, now we have a snackbar which shows the data is removed and Center widget if no other data is there.

Once we removed the data from add to favorites, then we need to refresh the page. which can be done by calling the fetchDatafromTable() once more. That is the reason for this after onPressed().

That's it. We have a working App which is up and running. Please do a clap if you like this. Comments are welcome.

If this story helps you to learn anything, please feel free to buy me a coffe

Links

  1. GitHub URL
  2. LinkedIn

--

--