After more than three years of working on the database abstraction as a side-project, the library is looking for a new home. I, unfortunately, currently can't dedicate as much time to maintaining the library as it deserves. Thereby, we're looking for a team that can better support the codebase and the community around Floor. Reach out to us through this form in case you're interested in taking ownership of the codebase.
The library started as a university project to implement and validate the hypothesis of whether porting an Android database library (Room) to Flutter is a good idea. By now, Floor evolved into one of the most popular choices when it comes to Flutter databases.
The project has received numerous contributions from volunteers, adding new features and bug fixes in their free time. Their work has been and will always be what makes the library. Thanks to every contributor!
See the project's website for the full documentation.
Floor provides a neat SQLite abstraction for your Flutter applications inspired by the Room persistence library. It comes with automatic mapping between in-memory objects and database rows while still offering full control of the database with the use of SQL. As a consequence, it's necessary to have an understanding of SQL and SQLite in order to harvest Floor's full potential.
- null-safe
- typesafe
- reactive
- lightweight
- SQL centric
- no hidden magic
- no hidden costs
- iOS, Android, Linux, macOS, Windows
Add the runtime dependency floor
as well as the generator floor_generator
to your pubspec.yaml
.
The third dependency is build_runner
which has to be included as a dev dependency just like the generator.
floor
holds all the code you are going to use in your application.floor_generator
includes the code for generating the database classes.build_runner
enables a concrete way of generating source code files.
dependencies:
flutter:
sdk: flutter
floor: ^1.2.0
dev_dependencies:
floor_generator: ^1.2.0
build_runner: ^2.1.2
It will represent a database table as well as the scaffold of your business object.
@entity
marks the class as a persistent class.
It's required to add a primary key to your table.
You can do so by adding the @primaryKey
annotation to an int
property.
There is no restriction on where you put the file containing the entity.
// entity/person.dart
import 'package:floor/floor.dart';
@entity
class Person {
@primaryKey
final int id;
final String name;
Person(this.id, this.name);
}
This component is responsible for managing access to the underlying SQLite database.
The abstract class contains the method signatures for querying the database which have to return a Future
or Stream
.
- You can define queries by adding the
@Query
annotation to a method. The SQL statement has to get added in parenthesis. The method must return aFuture
orStream
of theEntity
you're querying for. @insert
marks a method as an insertion method.
// dao/person_dao.dart
import 'package:floor/floor.dart';
@dao
abstract class PersonDao {
@Query('SELECT * FROM Person')
Future<List<Person>> findAllPersons();
@Query('SELECT * FROM Person WHERE id = :id')
Stream<Person?> findPersonById(int id);
@insert
Future<void> insertPerson(Person person);
}
It has to be an abstract class which extends FloorDatabase
.
Furthermore, it's required to add @Database()
to the signature of the class.
Make sure to add the created entity to the entities
attribute of the @Database
annotation.
In order to make the generated code work, it's required to also add the listed imports.
Make sure to add part 'database.g.dart';
beneath the imports of this file.
It's important to note that 'database' has to get exchanged with the filename of the database definition.
In this case, the file is named database.dart
.
// database.dart
// required package imports
import 'dart:async';
import 'package:floor/floor.dart';
import 'package:sqflite/sqflite.dart' as sqflite;
import 'dao/person_dao.dart';
import 'entity/person.dart';
part 'database.g.dart'; // the generated code will be there
@Database(version: 1, entities: [Person])
abstract class AppDatabase extends FloorDatabase {
PersonDao get personDao;
}
Run the generator with flutter packages pub run build_runner build
.
To automatically run it, whenever a file changes, use flutter packages pub run build_runner watch
.
For obtaining an instance of the database, use the generated $FloorAppDatabase
class, which allows access to a database builder.
The name is being composed by $Floor
and the database class name.
The string passed to databaseBuilder()
will be the database file name.
For initializing the database, call build()
and make sure to await
the result.
In order to retrieve the PersonDao
instance, invoking the persoDao
getter on the database instance is enough.
Its functions can be used as shown in the following snippet.
final database = await $FloorAppDatabase.databaseBuilder('app_database.db').build();
final personDao = database.personDao;
final person = Person(1, 'Frank');
await personDao.insertPerson(person);
final result = await personDao.findPersonById(1);
For further examples take a look at the example and test directories.
The library's name derives from the following. Floor as the bottom layer of a Room which points to the analogy of the database layer being the bottom and foundation layer of most applications. Where fl also gives a pointer that the library is used in the Flutter context.
For bugs please use GitHub Issues. For questions, ideas, and discussions use GitHub Discussions.
Copyright 2021 The Floor Project Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.