Go Offline with MongoDB Realm | by Markandey Pathak

Choosing a data store for mobile applications can be a daunting experience for Flutter developers

Photo by Caspar Camille Rubin on Unsplash

Realm’s mobile database is an open-source, developer-friendly alternative to KeyValue pairs, SQLite and Firestore. Start in minutes and save yourself weeks of work.

Realm is offline first, object-oriented, intuitive, and is built for mobiles.

In this article, we will build an offline mobile app using Flutter and Realm SDK.

What we will build?

We will be building a very simple Shopping List application where the user can view the list of items, add a new item, and toggle & delete existing items.

Application Screens

What you will need?

  • flutter installed & configured
  • your favorite IDE

Let’s get started

Start by creating a flutter app using the below command on your terminal.

flutter create shoppinglist

This will create a folder named shoppinglist in your current working directory which will contain the source code for your flutter application and will look something like this.

Open the directory as a project in your favorite IDE.

Install Realm as a dependency

Next, we will add realm as a dependency in our pubspec.yaml. This can be done using the below command

flutter pub add realm

Alternatively, you can open the pubspec.yaml file and add realm as a dependency:

dependencies:
# other dependecies here
realm: ^0.2.1+alpha

After adding the above, you need to run the below command:

flutter pub get

That’s it. Now you have everything you need to get started with Realm.

Create a Schema

Schema is the simplest unit in any Realm application. A schema defines the structure of data your application will be utilizing.

For example, an Item in our Shopping List can have two properties

  • text: string
  • done: boolean

To represent an Item in our application, we will create a Schema. To do that, create a directory named schemas in the lib directory. This directory will contain all the schemas used in the application.

Now create a file named item.dart with the below content.

@RealmModel is an Annotation class used to define Realm data model classes and their properties.

@PrimaryKey Indicates a primary key property. enables quick lookup of objects and enforces uniqueness of the values. It can be

applied to a single property in a RealmModel class

either String or int

Generate Schema from the RealmModel class

Now that we have our schema class defined, we need to generate the Realm schema. Realm schema is generated by combining the _Item and RealmObject classes. Realm has made this task simpler for us. All we need to do is to run the below command

flutter pub run realm generate

The above command will generate a new file item.g.dart containing a class Item.

Working with Realm

Configure and Open a Realm

To work with Realm, we first need to define a Configuration object. The constructor takes in a list of Schemas you want the Realm to work with. Optionally, you can pass a readOnly and inMemory flags indicating you want the Realm to be opened in read-only mode or Realm to be loaded in memory.

Configuration _config =
Configuration([Item.schema], readOnly: false, inMemory: false);
Realm _realm = Realm(_config);

Read all Items

RealmResults<Item> items = _realm.all<Item>();

Write/Update/Delete operations are done in a transaction block. To create a transaction block, use write() and provide a callback as a parameter. We perform the write/update/delete operation inside the callback.

Write an Item

_realm.write(() {
_realm.add<Item>(Item(text, false));
});

Update an Item

_realm.write(() {
item.done = true;
});

Delete an Item

_realm.write(() {
_realm.delete(item);
});

Close a Realm

if (!_realm.isClosed) {
_realm.close();
}

Create a Service for Realm operations

To manage our Realm, we will create a service class that will expose methods to open/close a realm and to perform query/update/delete operations on our Realm.

Create a directory services under lib directory. Add a new file item_service.dart with the following code

Now that our core business logic is ready, we will move to build the UI components and screen.

Create UI Components

Create a directory components in the lib directory. This directory will contain all the UI components used in our ShoppingList Application.

ItemListView

ItemListView is essentially a ListView which renders a list of Items in our Shopping List. ItemListView component takes three required parameters:

  • items – A list of Item objects
  • onToggle – A callback function to be invoked when an item is toggled
  • onDelete – A callback function to be invoked when an item is deleted

Add a new file named item_list_view.dart in components directory with the below code:

AddItemView

AddItemView is structured of an Input Field and a Button. Users can enter an item in the Input Field and when they click the Button, a new item should be created.

AddItemView component takes one required parameter:

  • onAdd – A callback function to be invoked when an item is added

Add a new file named add_item_view.dart in components directory with the below code:

ShoppingListView

ShoppingListView is composed of the previously created components ItemListView and AddItemView and presents an aggregated view where the user can add an item and view the List of existing Items.

ShoppingListView component takes four required parameters:

  • onAdd – A callback function to be invoked when an item is added
  • onToggle – A callback function to be invoked when an item is toggled
  • onDelete – A callback function to be invoked when an item is deleted
  • items – A list of Item objects

Add a new file named shopping_list_view.dart in components directory with the below code:

Create the Home Screen

Now that we have our UI components and Realm service ready, we can stitch them together on our Home Screen. On our home screen, we will render our main app with ShoppingList as a child. We will also create the callback functions onAdd, onToggle and onDelete and handle various Realm operations in these functions.

Open main.dart in lib directory and replace the existing code with the below:

Run Application

That’s it. Our application is ready to be launched. Save all the code files.

To launch the flutter application, we will first launch the emulator. Let’s find the list of available emulators.

flutter emulators

Pick one of the emulator IDs from the above output and launch one using the below command:

flutter emulators --launch Pixel4_API30

After the emulator is launched, you can find its device-id using the below command:

flutter devices

Copy the device-id (emulator-5554), and run the flutter app using the below command:

flutter run -d emulator-5554

If you are not a big fan of commands, you can use your IDE to launch emulators and run Flutter applications.

Tips & Further Resources

Now that you have a Realm application running, you can continue adding more schemas or update existing schemas.

Whenever you make a change to a schema, you need to run the below command to generate RealmObjects based on your schema definition.

flutter pub run realm generate

You can run the above command with a watch option to generate/update RealmObjects as and when you update your schema.

flutter pub run realm generate --watch

Please note, that when you update your realm schema, you need to DELETE your current realm. To do that, simply execute the below code before opening your realm.

Realm.deleteRealm(Configuration.defaultPath);

The source code for this application is available here

Realm Flutter is currently in Alpha stage. Realm is a very powerful ecosystem and is much more than a simple offline data store for your application. The realm team at MongoDB is working really hard to make various Realm features like Realm Sync, Realm Authentication, Realm Functions etc. available to Flutter developers.

To explore further on MongoDB Realm, you can visit the official documentation here.

Leave a Comment