Creating a Notes App for Web and Mobile using a local database

CodeGlich
Flutter Community
Published in
11 min readJan 16, 2020

Single code base using Flutter and Hive to create a Web and Mobile Notes app with a local database.

Photo by Andrew Neel on Unsplash

As a test to using Flutter, I thought next I would make my own note taking app, for both Web and Mobile. Since I come from a Web background, It would be nice to have a single code base for Web and Mobile, but I can imagine this is not an easy task.

On my path to learning Flutter, I think this app could have a lot of useful research for my future projects, I already worked with Maps, Form, and Web API, with this project I should be able to cover local storage needs.

The code for this project can be found at:

Since at the moment Flutter Web is in Beta, I will be working on the channel beta (channels are different stages of Flutter development, by default we start with stable), beta is usually stable but you could still find some bugs. (info on Flutter build release channels)

Changing the Flutter channel is easy enough, I just have to open my terminal and run:

$ flutter channel beta

Command!

After it’s done switching, all I have to do is $ flutter upgrade and it’s done!

Now I’m going back to my IDE of choice (for now is Visual Studio Code), “Ctrl-Shift-P”, to display my cmd palette and create my new project “flutter_notes”!

New Project!

First thing I do after creating the project: clear the comments, and extra code.

Second, there should already be a “web” folder at the root of the project, if not check how to make your project web compatible.

Web Support

Getting started with Hive

If i didn’t want to have Web compatibility, I would go with “sqflite” because I’ve used it before, but since it doesn’t work with web I’m going to try “hive”:

web!
Hive Features

From my first look at the documentation and feedback, it looks like a very interesting project.

Now before I go any further, I’m going to think about my notes Database structure.

Diagram

I’ve added “position” because I want to add manual reorder for the notes and note items.

Before I go continue, I like to create a folder called “data”, this is where we will keep classes for the Data.

folder tree

The way of creating classes for Hive is a little different, I’ve used this as a guide to get started.

Adding hive to my project

I will not only add hive, I will also update the min sdk do 2.6.0:

pubspec.yaml

Later “hive_generator” and “build_runner” will be required to generate the adapters using hive.

Creating my Hive Class:

hiveDB.dart

There is something different on this file, “part ‘hiveDB.g.dart’;”, this part will be generated when I create the adapter for my Custom Class using the cmd, there will be a new file automatically generated with that name.

To generate the adapter just run:

$ flutter packages pub run build_runner build --delete-conflicting-outputs

Generating my adapter
file generated

After that is done, you can see the new file on the project

The code generated can be seen here!

Registering the Adapter

To be able to use a generated adapter, you need to register it.

Registering the adapter will be done inside the main, for that I will need to change main from this: “void main() => runApp(MyApp());”, to this:

New main
My tree!

I also took the time to create my usual “code” folder, this is where I will keep my most used/shared content. For now I will create a “config.dart” for shared variables, like “notesBox” where I will keep the box name.

The same name must be used to access the Data, is like creating a Database, if it has a different name, it has different Data! There are times where I could want to keep data in separated Boxes, this won’t happen at this time.

Creating my UI

At this point I’m thinking about displaying notes using tiles, and add new notes using a floatingActionButton.

Build

main.dart

I prefer dark themes, so I went with “ThemeData.dark()” as a default theme choice.

As usual I like to get my body and buttons from a separated function, instead of doing it directly. The “getNotes“ function will use a “ValueListenableBuilder” so that the Notes list get updated every time there is a change, this is only possible because Hive Boxes have a “listenable” function to notify of changes.

Bonus! The Flutter team even made it the widget of the week!

Body

getNotes()

If there are Notes inside the Hive Box, it will be returned from the function, at the moment they are returned with “position ascending” order. To be able to reorder the notes, I will get them as a List, and do the reorder after that:

get notes list ordered

Other function that we can see inside the “getNotes” is the “getNoteInfo”, this will return the ListTile for the note been added to the list (I will be adding a delete/more info icon here later):

getNoteInfo

The thing to point out about the body, is that the List Tiles are all inside a ReorderableListView, instead of the usual ListView, this is so that the order of the notes can be changed, for that the items inside it need to have a key and the ReorderableListView needs a onReorder function:

reorderNotes

Note about ReorderableListView:

Don’t add other items besides the ListTiles, it will mess up the index because it wont be the same as the List.

Adding Notes

For adding notes I will use a “floatingActionButton”, which will be returned from “addNoteButton”:

addNoteButton

I’m going to use the Navigator to open a new screen called “AddNote”, this is where we are going to create new Notes.

screens

For new screens the file will be created inside the “screens” folder.

In the new screen I will create a Form for filling the new Note info:

New Note

This screen is mostly a standard Form, the main difference is in the buttons.

In the buttons for creating one of the Note types, we will be creating a new Hive entry for the Box I had created at the beginning, and after that I will add a new entry to the corresponding Box:

buttons

I’ve decided to add the Notes Items in each separated Box, list of Boxes:

  • Notes
  • Text Note Items
  • Check List Note Items

This follows the diagram I created earlier.

The last thing added to code was the function “reorderNotes“, this will be called when creating a new Note, all it will do is increase the position of the already inserted notes by one, and always giving the new Note the position 0 (for the ascending order).

New note created!

After a Note is insert the screen closes and goes back to the main screen, where we should see the new Note (thank you listenable())

And does it work on the web?

works!

Editing Notes

For the task of editing Notes I will need a screen for each type.

Going back to main.dart

I’m going to alter the ListTile to support a onTap event, this will open the corresponding Widget for the Note Type:

getNoteInfo 2.0

In the same way we navigate to create a new Note, the same will be done for editing. To edit the note its going to be required the “note.key” and “note.title”, to identify by the Parent id and add the title to the new screen AppBar.

Text Notes

Going to get started with the easy one, I’m going to get the Item for this note and assign it to the “TextEditingController”, this makes it easier to load/save the content:

loading text note

Using the parent key that was passed earlier, a search can be done for the corresponding item of that Note using the “singleWhere” method. The result is going to be saved because this item is going to be edited and saved again in the box:

saving text note

When the save button is pressed, the text in the “TextEditingController” is going to the TextNote that was loaded earlier, and using the put method from Hive, I’m going to update the item the Box with that key value.

Text Note editing!

Check List Notes

This is where things start to get a little tricky for me…

This one is going to be a little different, since there could be many items inside a Check List, we will need to handle an array.

Like on the Text one, we start with the Parent ID, with that I can load all the Check List items to a List. This function will be called at the beginning/adding notes/deleting notes process. The item order will start from position 0, we will add reorder later (also ascending).

loading check list note items id

With that done I can use that array to fill a ListView with ListTiles, each tile will have the check box, text, and delete button. Another extra is the key value, key value has to be unique (I’m using the Hive Box item key), this will be used to replace “ListView with “ReorderableListView”. This piece of code will be bigger but I like to give the full picture:

check list edit

Breaking it down

At start we use loadNoteItems() to fill our array of CheckListNote items. The body like before will be made of a SafeArea (just to be safe) and a ListView. If there is nothing in the array, we get a simple “No items” text, else I’m using the spread operator with a “for” to fill the ListView with ListTiles. In the ListTile the leading widget will be the check box for the done option, title widget will be for the editable Text Field, and last the trailing widget will be used for the delete icon.

The last thing to note in the ListTile is that I’ve made a small StatelessWidget for the Text Field, it will update the item inside the Box container, but there is no need to update the view (State):

filling the ListTiles

The “CheckBox” uses the same put() function Hive to update the Box, but before that it also calls a function “getUpdateItemInfo(item);”, this is done because since we are calling a setState, if the item’s text was changed, this will update the item in the initial List (to avoid overwriting the old title):

getUpdateItemInfo

“CheckListItemText” requires the item ID for updating it later. Snipped for the text field widget:

CheckListItemText

For adding new items to the list, I will use yet again my faithful floatActionButton:

adding new item

Like I did when creating notes, I’m going to add the new item at position 0 and reorder all existing items to +1. After that is done loadingNoteItems() and setState will do the rest.

How does it look like so far:

Check List Items

Now the last thing to add to this screen is reordering, for this I will go the easy way and replace the ListView with a ReorderableListView (it was also widget of the week!), all it requires is a unique key (that I already had before) for every item and a onReorder function to update the item position both in the Hive Box and the List (the reorder function is pretty much the same that was used to edit the Notes position on the main screen):

ReorderableListView

Result:

drag and drop video

Bonus:

To keep track of when a note was last changed, I went to my “code” folder and created a “code.dart” file, this will have a function to update the Note “dateUpdated”:

code

This function will be called when changes are made to a note, usage example:

Code().changeUpdatedDate(widget.noteParent);

Viewing/Editing Note

Going to create a new screen for editing the Note title/description or simply for deleting it. I’m going to add a new file to my screens folder, “edit_note.dart”.

Back at my “main.dart” I’m going to add a trailing Icon to the ListTile for navigation:

adding info icon to ListTile

The new screen will receive the unique note Key, which is provided by the Box!

In the new screen we will also be displaying the created and updated date/time info, for that I want to format the date, we will need to add the “intl” package and add a new function to my “code.dart”:

intl

At build I’m going to use the singleWhere I’ve used before to get the Note info :

edit note screen

The form is mostly the same as it was for creating the Note, but the buttons functions have changed:

Edit/Delete screen

For the save button its pretty simple:

updateNoteInfo

For the Delete button it will also be very simple, the only new thing here is the “AlertDialog”, this allows to get a action confirmation from the user:

deleteNote
confirmation

Conclusion

There was (is) a lot to learn about Hive, I’ve had a pretty good experience with it, and it’s very different (for me) compared MS SQL which I’m most used to.

The main thing I took out of this project was that it was easier to debug on the Android and try to see if it works on the Web too after, there were times when there was bugs but there was no clear way of seeing the error output. But this is something that is only related to Flutter, since web is still is in Beta there are some tools that need to be added for the Web development to be smooth too.

One code base is pretty good, and there is still a lot of work to be done. But the “code once, work everywhere” is possible (even if hard).

I hope the Flutter team keeps the good work on the Web integration, enabling more single code base projects!

PS: Since Hive uses local data storage, if for some reason the storage is cleared, notes will be lost! A good next step would be to make the notes synchronize with a server or some storage, or export them.

Flutter Notes (web)

screen recording

--

--