7a9cafb02f | ||
---|---|---|
.. | ||
android/app/src/main/java/io/flutter/plugins | ||
example | ||
lib | ||
.flutter-plugins | ||
.gitignore | ||
.metadata | ||
CHANGELOG.md | ||
LICENSE | ||
README.md | ||
pubspec.lock | ||
pubspec.yaml |
README.md
Moor
Moor is an easy to use, reactive persistence library for Flutter apps. Define your database tables in pure Dart and enjoy a fluent query API, auto-updating streams and more!
Here are just some of the many features moor provides to make dealing with persistence much easier:
Declarative tables
With moor, you can declare your tables in pure dart without having to miss out on advanced sqlite
features. Moor will take care of writing the CREATE TABLE
statements when the database is created.
Fluent queries
Thanks to the power of Dart build system, moor will let you write typesafe queries:
Future<User> userById(int id) {
return (select(users)..where((user) => user.id.equals(id))).getSingle();
// runs SELECT * FROM users WHERE id = ?, automatically binds the parameter
// and parses the result row.
}
No more hard to debug typos in sql, no more annoying to write mapping code - moor takes care of all the boring parts. Moor supports features like order by statements, limits and even joins with this api.
Prefer SQL? Moor got you covered
Moor contains a powerful sql parser and analyzer, allowing it to create typesafe APIs for all your sql queries:
@UseMoor(
tables: [Categories],
queries: {
'categoryById': 'SELECT * FROM categories WHERE id = :id'
},
)
class MyDatabase extends _$MyDatabase {
// the _$MyDatabase class will have the categoryById(int id) and watchCategoryById(int id)
// methods that execute the sql and parse its result into a generated class.
All queries are validated and analyzed during build-time, so that moor can provide hints about potential errors quickly and generate efficient mapping code once.
Auto-updating streams
For all your queries, moor can generate a Stream
that will automatically emit new results
whenever the underlying data changes. This is first-class feature that perfectly integrates
with custom queries, daos and all the other features. Having an auto-updating single source
of truth makes managing perstistent state much easier!
And much moor...
Moor also supports transactions, DAOs, powerful helpers for migrations, batched inserts and many more features that makes writing persistence code much easier.
Getting started
For a more detailed guide on using moor, check out the documentation.
Adding the dependency
First, add moor to your project's pubspec.yaml
.
dependencies:
moor_flutter: # use the latest version
dev_dependencies:
moor_generator: # use the latest versions
build_runner:
Declaring tables
You can use the DSL included with this library to specify your libraries with simple dart code:
import 'package:moor_flutter/moor_flutter.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: 10)();
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 only 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 of the
// tables we just defined. We'll see how to use that database class in a moment.
@UseMoor(tables: [Todos, Categories])
class MyDatabase {
}
⚠️ Note: The column definitions, the table name and the primary key must be known at
compile time. For column definitions and the primary key, the function must use the =>
operator and can't contain anything more than what's included in this readme
and the
examples. Otherwise, the generator won't be able to know what's going on.
Generating the code
Moor integrates with the dart build
system, so you can generate all the code needed with
flutter packages pub run build_runner build
. If you want to continuously rebuild the generated code
whenever you change your code, run flutter packages pub run build_runner watch
instead.
After running either command once, the moor generator will have created a class for your
database and data classes for your entities. To use it, change the MyDatabase
class as
follows:
@UseMoor(tables: [Todos, Categories])
class MyDatabase extends _$MyDatabase {
// we tell the database where to store the data with this constructor
MyDatabase() : super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite'));
// you should bump this number whenever you change or add a table definition. Migrations
// are covered later in this readme.
@override
int get schemaVersion => 1;
}
You can ignore the schemaVersion
at the moment, the important part is that you can
now run your queries with fluent Dart code:
Writing queries
// inside the database class:
// loads all todo entries
Future<List<Todo>> get allTodoEntries => select(todos).get();
// watches all todo entries in a given category. The stream will automatically
// emit new items whenever the underlying data changes.
Stream<List<TodoEntry>> watchEntriesInCategory(Category c) {
return (select(todos)..where((t) => t.category.equals(c.id))).watch();
}
}
Visit the detailed documentation to learn about advanced features like transactions, DAOs, custom queries and more.