Moor in Flutter(Tables and Queries)
Moor is just a Room spelled backward. Moor is a library allowing us to work with Flutter’s SQLite database fluently and in pure Dart. Moor also uses SQLite package. In flutter, it becomes very easy to create a database without writing code for SQL tables. Moor itself uses SQL as its backend so in flutter we can directly create a Table using Dart
Table of content
Why Moor?
- Moor enables us to write queries in dart and SQL.
- Provide us APIs in dart as well.
- Moor provides Tables, queries, migration, IDE for SQL, complex filters.
- Moor helps you keep your database code simple and easy to understand.
- Identify or catches the error and provides the solution
- Moor is fast like FLUTTER.
- Moor works on Android, iOS, macOS, Windows, Linux, and the web.
- Moor is stable and well tested with a wide range of unit and integration tests. It powers the production of Flutter apps.
Adding the dependency
- moor_flutter:
This is the core package that provides APIs.
2. moor_generator:
Generate query code based on the Table defined by the user.
3. build_runner:
Tool for database code generation.
4. pubspec.yaml
dependencies:
moor_flutter:
dev_dependencies:
moor_generator:
build_runner:
Creating a Table
A Table in dart is made by just extending our dart class to Table. Moor uses this Table and database class to create a Database.
- SQL Table in dart
import 'package:moor_flutter/moor_flutter.dart';
part 'moor_database.g.dart';
class Orders extends Table {
TextColumn get price => text()();
IntColumn get id => integer().autoIncrement()();
TextColumn get productName => text()();
}
@UseMoor(tables: [Orders])
class AppDatabase{
}
Here IntColumn, TextColumn are the Table datatypes that are used to define the type of data that will the column of Table carries.
part 'moor_database.g.dart';
This is the file name that will contain the code generated using the Table. The id for each item in a column is id since it is autoIncrement().
2. Custom key
We can also provide our custom id to the table by just overriding the primaryKey.
@override
Set<Column> get primaryKey => {id, productName};
The Database class
@UseMoor(tables: [Orders])
class AppDatabase extends _$AppDatabase {
AppDatabase()
: super(FlutterQueryExecutor.inDatabaseFolder(
path: "db.sqlite", logStatements: true));
int get schemaVersion => 1;
}
After creating this Database class we need to generate the moor_Database.g.dart file. So we have to run the below command in the terminal.
flutter packages pub run build_runner build
Here we are defining the path inside the Database folder and we are setting the logStatements to true. It will help in debugging.
Queries
These queries are given inside the AppDatabase class.
- Queries in pure Dart with moor
Future<List<Order>> getAllOrder() => select(orders).get();
Stream<List<Order>> watchAllOrder() => select(orders).watch();
Future insertNewOrder(Order order) => into(orders).insert(order);
Future deleteOrder(Order order) => delete(orders).delete(order);
select()
You can create select
statements by starting them with select(tableName)
, where the table name is a field generated for you by the moor. Each table used in a database will have a matching field to run queries against. Any query can be run once with get()
or be turned into an auto-updating stream using watch()
.
Future<List<Order>> getAllOrder() => select(orders).get();
Stream<List<Order>> watchAllTask() => select(orders).watch();
insert() & delete()
We can also insert any object into the Table.
insert and delete statement take a Tables, in this case, we have Order as our Table.
Future insertNewOrder(Order order) => into(orders).insert(order);
Future deleteOrder(Order order) => delete(orders).delete(order);
update()
This statement also uses the Table to update the targeted attribute using the constructor of the Table.
Future updateOrder(Order order) => update(orders).relpace(order);
2. Full Code for moor_database.dart file
import 'package:moor_flutter/moor_flutter.dart';
part 'moor_database.g.dart';
class Orders extends Table {
TextColumn get price => text()();
IntColumn get id => integer().autoIncrement()();
TextColumn get productName => text()();
}
@UseMoor(tables: [Orders])
class AppDatabase extends _$AppDatabase {
AppDatabase()
: super(FlutterQueryExecutor.inDatabaseFolder(
path: "db.sqlite", logStatements: true));
int get schemaVersion => 1;
Future<List<Order>> getAllOrder() => select(orders).get();
Stream<List<Order>> watchAllOrder() => select(orders).watch();
Future insertNewOrder(Order order) => into(orders).insert(order);
Future deleteOrder(Order order) => delete(orders).delete(order);
}
3. Generated file code
https://gist.github.com/anmolseth06/8115030632c51f498a4cd393e777d192#file-moor_database-g-dart
User Interface
- User Input Widget
TextField(
decoration: InputDecoration(hintText: 'Product Name'),
keyboardType: TextInputType.text,
controller: productNameController,
),
TextField(
decoration: InputDecoration(hintText: 'Product Price'),
keyboardType: TextInputType.number,
controller: priceController,
),
RaisedButton(
onPressed: () {
setState(() {
AppDatabase().insertNewOrder(Order(
price: priceController.text,
productName: productNameController.text,
));
priceController.clear();
productNameController.clear();
});
},
color: Colors.green,
child: Text("Place Order"),
),
We are using setState state management to control the state of the widgets.Onpressing the Raised Button price and productName are made equals to the priceConroller and productNameController.
.text converts the TextEditingController() to text
2. ListView of Orders
This widget contains the list of all the orders that the user provides using the UserInput widget.
StreamBuilder is used to listen to the stream watchAllOrder().
ListTile contains a CircleAvatar, title, subtitle, and trailing.
snapshot.data is the list of all the Orders that are fetched from the local database.
StreamBuilder(
stream: AppDatabase().watchAllOrder(),
builder: (context, AsyncSnapshot<List<Order>> snapshot) {
return ListView.builder(
itemBuilder: (_, index) {
return Card(
color: Colors.orangeAccent,
child: ListTile(
leading: CircleAvatar(
child: Text('${index + 1}'),
radius: 20,
),
title: Text(snapshot.data[index].productName),
subtitle: Text("Rs. ${snapshot.data[index].price}"),
trailing: IconButton(
icon: Icon(Icons.delete_outline),
onPressed: () {
setState(() {
AppDatabase().deleteOrder(snapshot.data[index]);
});
},
color: Colors.red,
)),
);
},
itemCount: snapshot.data.length,
);
},
),
Full Project
flutter-devs/moor_database_example
A new Flutter application. This project is a starting point for a Flutter application. A few resources to get you…github.com
Thanks for reading this article ❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
If we got something wrong? Let me know in the comments. we would love to improve.
Feel free to connect with us:
And read more articles from FlutterDevs.com
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, and Twitter for any flutter related queries.
We welcome feedback, and hope that you share what you’re working on using #Flutter. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!
Thank you for reading. 🌸