Top Database Solutions for Flutter Application

Regardless of who you are or what you do, you’ll need to save data in your flutter app and access it later at some point. But how do you go about doing it? The short answer, you can use a database inside your Flutter app. So, in this article, we will be taking a look at the best databases available for use with Flutter applications.

When it comes to database in your flutter application, you have a lot of choices today. They usually fall into one of three groups:

  • Relational – Databases in the classic meaning are relational databases. They don’t just store data; they also store data relationships. A relational database, such as SQLite, is an example.
  • NoSQL – NoSQL databases hold data in the form of documents. In contrast to a relational database, a schema is not enforced. They are lightning fast and excel at handling large amounts of unstructured data. A NoSQL database, for example, is MongoDB.
  • Individually tailored data storage – you don’t have to utilize the preceding solutions because this option isn’t technically a database. You can save your data in a JSON file and do your own serialization and deserialization. This would be extremely fast, but if you weren’t a programming genius, you’d be vulnerable to some strange flaws.

Relational Databases In Flutter

Relational databases have existed for quite some time (since 1970, according to a quick Google search). Let’s take a look at some of the relational database solutions available on Flutter nowadays.

SQflite: SQL Database For Flutter

SQflite is a SQLite implementation for Flutter. It gives you complete control over your database, queries, and relationships, as well as anything else.

In Flutter, interacting with a SQLite database looks like this:

// Get a location using getDatabasesPath var databasesPath = await getDatabasesPath(); String path = join(databasesPath, 'demo.db'); // Delete the database await deleteDatabase(path); // open the database Database database = await openDatabase(path, version: 1, onCreate: (Database db, int version) async { // When creating the db, create the table await db.execute( 'CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, num REAL)'); }); Inserting data follows the same age-old SQLite tenants // Insert some records in a transaction await database.transaction((txn) async { int id1 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES("some name", 1234, 456.789)'); print('inserted1: $id1'); int id2 = await txn.rawInsert( 'INSERT INTO Test(name, value, num) VALUES(?, ?, ?)', ['another name', 12345678, 3.1416]); print('inserted2: $id2'); });
Code language: JavaScript (javascript)

And here’s how querying works:

// Get the records List<Map> list = await database.rawQuery('SELECT * FROM Test');
Code language: JavaScript (javascript)

Advantages

  • The database is completely under your control.
  • A very efficient SQLite database for Flutter (given that you have pre-existing SQLite knowledge).
  • Third-party apps that can open SQLite databases can easily read it (so you can open the database on your computer and see what the data looks like).

Disadvantages

  • It can take a long time to write out all of your questions by hand.
  • The data returned from the database isn’t strongly typed right away.
  • Handling migrations on the device could be tough (when the schema changes between version updates for instance).
  • There is no web support.

SQFlite is useful when you need relational data as well as fine-grained query control. This could be a good fit for you if you’re comfortable building your own queries and don’t mind writing a lot of queries as well as the code to convert the results to and from your classes.

Moor: SQL Database For Flutter

To utilize Moor, we first need to import the Moor package from, but we also need to import the moor generator. This is used by build runner to generate database-related code.

What is the purpose of using build runner?

The main purpose of build runner is to produce code for your Flutter projects. I rarely, if ever, had to use a code generating utility before coming to Flutter. The main reason for this is because most of the other languages I’d used before (such as C#) supported reflection.
Simply expressed, this enables the framework to dynamically invoke portions of the program during execution. It has a lot of power, but it’s also pretty slow. As with reflection, it has an impact on connectivity of the resulting application; technically, any portion of your application could be accessible or used.
When packages rely on reflection for functionality, they commonly utilize build runner to generate the necessary code ahead of time. This leads to speedier code execution at runtime, as well as better ‘tree shaking,’ or application binary minimization, at deployment time.

A look into the getting started documentation helps us understand the way a database is created.

import 'package:moor/moor.dart'; // assuming that your file is called filename.dart. This will give an error at first, // but it's needed for moor to know about the generated code part 'filename.g.dart'; // this will generate a table called "todos" for us. The rows of that table will // be represented by a class called "Todo". class Todos extends Table { IntColumn get id => integer().autoIncrement()(); TextColumn get title => text().withLength(min: 6, max: 32)(); TextColumn get content => text().named('body')(); IntColumn get category => integer().nullable()(); } // This will make moor generate a class called "Category" to represent a row in this table. // By default, "Categorie" would have been used because it strips away the trailing "s" // in the table name. @DataClassName("Category") class Categories extends Table { IntColumn get id => integer().autoIncrement()(); TextColumn get description => text()(); } // this annotation tells moor to prepare a database class that uses both tables // we just defined. We'll see how to use that database class in a moment. @UseMoor(tables: [Todos, Categories]) class MyDatabase { }
Code language: PHP (php)

Moor builds the schema for your tables programmatically based on how you describe their contents. The part statement appears at the start of this code example. When we run the build runner command, it creates the schema from the information in this file. If you need to execute a specific query or want more fine-grained control, you may switch back to raw SQL at any time.

Advantages

  • Strongly Typed results.
  • Operation is based upon SQLite.
  • No need to manually compose each query.
  • Code generation takes care of a lot of the heavy lifting.
  • A large number of tools are available now to examine data in SQLite databases during development.

Disadvantages

  • Managing schema updates on a local device can be inconvenient.
  • The web support is still in beta.
  • There are platform-specific requirements in it (not written in pure Dart).

This could be a good fit for you if you still need relational data but want to write as little SQL as possible (for example, if you’re used to Entity Framework).

NoSQL Databases In Flutter

When it comes to NoSQL databases for Flutter, there are a lot of alternatives. We have the heavy hitters, such as Firebase, that have been around for a long time, as well as the newer options, such as Hive. There are several distinctions between Hive and Firebase, but one of the most notable is that one may sync to an internet store (Firebase), and the other is better suited for keeping locally on the device (Hive).

Cloud Firestore: Online NoSQL Database For Flutter

Firebase is a document storage database in the classic sense. Data is saved in collections, which are similar to tables in a typical database. Documents are stored in these collections. Data types such as string, int, and others are stored in documents. They can also store a link to another document, so you can construct associations between your data even if Firebase isn’t exactly relational.

Firebase requires more setup than other on-device solutions like Hive, but it provides data synchronization between clients and the server. This means that if you have numerous clients using an app and they’re all engaging with the same data, the data may be kept in sync. In addition, this arrangement is well-covered in a. The only disadvantage of this strategy is that it does not provide tightly typed data in the same way as Moor or Hive do. You must deal with this on your own.

Advantages

  • Synchronizes with Firebase in near-real-time across the internet.
  • Excellent tooling assistance.
  • The Firebase Console makes it simple to browse data online.

Disadvantages

  • If you haven’t already integrated Firebase into your app, the setup can be challenging.
  • Because the database is online, you must consider a lot more when developing your Flutter application than you would with a database that is only on your device (like access permissions, for instance).
  • Flutter support in Firebase isn’t quite ready for prime time yet.

This could be an excellent choice for you if your data will be scattered over multiple devices and you want (relatively) painless synchronization across them.

Hive: NoSQL Database For Flutter

For Flutter developers, Hive provides a lightning-fast NoSQL storage alternative. The fact that it is totally Dart-native is its major selling feature. Hive can go wherever Dart can because it doesn’t require any device-specific implementations.

Hive allows you to store data as a HiveObject, which allows for various object-to-object relationships. It keeps things in a box, but TypeAdapters can be created for them.

It’s not difficult to make a box:

var box = await Hive.openBox('testBox');
Code language: JavaScript (javascript)

It’s equally as simple to read and write:

import 'package:hive/hive.dart'; void main() async { var box = await Hive.openBox('testBox'); box.put('name', 'David'); print('Name: ${box.get('name')}'); }
Code language: JavaScript (javascript)

Hive’s ability to generate TypeAdapters is where it really shines (read more from the ). This gives your Boxes robust type and allows you to store classes as well as reference objects in other Boxes.

The manual explains how to make a box based on a class that you define yourself, as shown below.

import 'package:hive/hive.dart'; part 'person.g.dart'; @HiveType() class Person { @HiveField(0) String name; @HiveField(1) int age; @HiveField(2) List<Person> friends; }
Code language: JavaScript (javascript)

This class, as we can see, contains a List of Person, allowing Hive to refer to a list of objects.

Hive is for you if you just need a simple database to store data on your smartphone and don’t need the synchronization that Firebase provides, as well as something that works anywhere. It’s the database that all of my apps rely on.

Conclusion

It’s difficult to say which database is “better” because it depends on your needs. But allow me to summarize.

  • You should utilize moor if your data is relational and you want to be able to access it quickly on your computer during development – and you don’t mind not having web support.
  • If you require your data to be synchronized between devices and don’t mind a lengthy setup, Firebase is the way to go.
  • Hive is the way to go if you want to get up and running quickly and have fantastic support for the web and anything else Dart runs on.

In this article we looked at some of the top SQL and NoSQL Database solutions available for the Flutter Framework. We also covered the fundamentals of each database’s operations, how to get each database up and running and, what an appropriate use case for each database would be? As always, If you have found this article useful do not forget to share it and leave a comment if you have any questions. Happy Coding 🙂

%d bloggers like this: