I am looking to define best development practices with Flutter and ObjectBox (1.1.1 -> Flutter).
I would like to set up an architecture composed of Repository to implement my query functions on objects stored in the database. Here is an example for an Object Person. Repositories will mainly be called from viewModels.
import 'package:flutter_app_best_practice/data/person_repository_interface.dart';
import 'package:flutter_app_best_practice/model/person.dart';
import 'package:flutter_app_best_practice/objectbox.g.dart';
import 'package:objectbox/objectbox.dart';
class PersonRepository implements IPersonRepository{
var _store;
late Box _box;
@override
Future<List<Person>>? getPeople() {
List<Person> list = _box.getAll() as List<Person>;
return Future.value(list);
}
@override
Future<void>? addPerson(String name, int age) async {
Person person = new Person();
person.name = name;
person.age = age;
_box.put(person); // Add
return;
}
@override
Future<void>? initialize() async {
// Future<Store> openStore() {...} is defined in the generated objectbox.g.dart
openStore().then((Store store) {
_store = store;
});
_box = _store.box<Person>();
return;
}
}
Here are my questions:
How do you think about this implementation :
class PersonRepository implements IPersonRepository {
@override
Future<List<Person>>? getPeople() async {
late List<Person> persons;
await openStore().then((Store store) {
var _box = store.box<Person>();
persons = _box.getAll();
store.close();
});
return Future.value(persons);
}
@override
Future<void>? addPerson(String name, int age) async {
await openStore().then((Store store) {
var _box = store.box<Person>();
Person person = new Person();
person.name = name;
person.age = age;
_box.put(person); // Add
store.close();
});
return;
}
}
Or call _store.close with this architecture ?
You can ignore Store.close()
in normal applications without excessive amount of background operations.
Instead of having an Initialize function, would it be better to open the store before each transaction and then close it after the transaction is complete?
No, opening a store is "rather" costly so you shouldn't do it on every store access - it's just going to slow things down for you and there's no benefit.
Are there examples of a similar structure using this latest version of objectBox (using openStore (). Then ((Store store))
There's an example in the objectbox package itself, albeit with a different code structure: https://github.com/objectbox/objectbox-dart/blob/main/objectbox/example/flutter/objectbox_demo/lib/main.dart#L79
To give you one example what you could do, while keeping the level of abstraction your code tries to do:
class PersonRepository implements IPersonRepository {
final Store _store;
final Box<Person> _box;
PersonRepository(this._store) : _box = _store.box() {}
@override
Future<List<Person>>? getPeople() {
List<Person> list = _box.getAll() as List<Person>;
return Future.value(list);
}
@override
Future<void>? addPerson(String name, int age) async {
Person person = new Person();
person.name = name;
person.age = age;
_box.put(person); // Add
return;
}
}
abstract class IDatabaseRepositories {
IPersonRepository get people;
}
class ObjectBoxRepositories implements IDatabaseRepositories {
final Store _store;
final PersonRepository people;
static Future<IDatabaseRepositories> create() async =>
ObjectBoxRepositories._(await openStore());
ObjectBoxRepositories._(this._store) : people = PersonRepository(_store);
}