如何在 Flutter 中 access/inject 存储库中的 ObjectBox 数据库 - Reso Coder DDD

How to access/inject ObjectBox database in repository in Flutter - Reso Coder DDD

我看到的所有示例都是在 State(less/full)Widget 中初始化 ObjectBox。我正在使用分层架构(目前正在重构为 DDD)并且想知道如何正确地注入我的 ObjectBox。

在我的存储库中,我使用 injectable 和 getit 包注入数据源

@injectable
@LazySingleton (as: IJournalsRepository)
class JournalsRepository implements IJournalsRepository {
  final JournalsRemoteDataSource journalsRemoteDataSource;
  final JournalsLocalDataSource journalsLocalDataSource;
  JournalsRepository(this.journalsLocalDataSource, this.journalsRemoteDataSource);

这些包然后创建 JournalsRemoteDataSourceJournalsRemoteDataSource 的实例并将其注入存储库。

ObjectBox 示例显示初始化

class _MyHomePageState extends State<MyHomePage> {
  Store? _store;
  @override
  void initState() {
    super.initState();
    openStore().then((Store store) => _store = store;);
  }

  @override
  void dispose() {
    _store?.close();  // don't forget to close the store
    super.dispose();
  }
}

所以我不知道注入器如何初始化 ObjectBox,或者如果我在 MyApp()HomePage 的上游)

PS:在每个 read/write 事件中重新打开 JournalsRemoteDataSource 中的框性能非常差

==========更新========== 补充我对@vaind

的评论

我同时在这个类似的 上找到了你的答案(不知道为什么我一开始没有看到它)。我希望这种方法也能在这里发挥作用。但是,我在初始化商店时仍然遇到问题。我的原型来自 Firestore,看起来像这样:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:injectable/injectable.dart';

@module
abstract class FirebaseInjectableModule {
  @lazySingleton
  FirebaseAuth get firebaseAuth => FirebaseAuth.instance;
}

虽然我不明白 getter firebaseAuth 是从哪里来的,也没有找到任何解释。无论如何,我将其改编为

import 'package:injectable/injectable.dart';
import 'package:objectbox/objectbox.dart';
import 'package:test/objectbox.g.dart';

@module
abstract class ObjectboxInjectableModule {
  @lazySingleton
  Future<Store> get store async => await openStore();
}

并将其与

一起使用
@LazySingleton (as: ILocalDataSource)
class ObjectBoxDataSource implements ILocalDataSource {
  final Store _store;
  final Box<JournalOboxEntity> _box;
  ObjectBoxDataSource(this._store) : _box = _store.box();

除了 final Store _store 在 IntelliJ 中是灰色的(未使用的变量),我收到错误

You tried to access an instance of Store that is not ready yet
'package:get_it/get_it_impl.dart':
Failed assertion: line 404 pos 9: 'instanceFactory.isReady'

我没有使用软件包 get_itinjectable 的经验,但根据文档,我认为以下替代方法可行。直接使用 get_it,不确定使用 injectableget_it 的生成器)实现相同的正确方法,但我想如果您熟悉它,您可以配置它来生成相同的代码。

备选方案 A,惰性(异步)单例

GetIt.I.registerSingletonAsync<Store>(openStore);

备选方案 B,在 main() 中设置,可能更可取

将您的 main 更改为:

void main() async {
  GetIt.I.registerSingleton<Store>(await openStore());
  runApp(MyApp());
}

注意:看起来 get_it 提供了一种重置方法,这将导致重新打开同一家商店。为避免使用它时出现问题,您还需要实施 get_itdispose 版本,该版本调用 store.close().

所以在vaind的另一个回答之后,我实现了如下。我的架构遵循 Reso Coder 的 DDD 和 Clean Architecture 教程的合并。基本上它是 DDD 与 Clean Architecture 的 local/remote 数据源层。

INFRASTRUCTURE 目录

抽象数据源

abstract class ILocalDataSource {
  Future<JournalDto> getJournal(int id);
  Future<void> storeJournal(JournalDto record);
}
abstract class IRemoteDataSource {
  Future<JournalDto> getJournal(int problemClassId);
}

数据源实现

@LazySingleton (as: ILocalDataSource)
class ObjectBoxDataSource implements ILocalDataSource {
  final Store _store;
  final Box<JournalOboxEntity> _box;
  ObjectBoxDataSource(this._store) : _box = _store.box();

infrastructure/core

中的可注入模块
@module
abstract class ObjectBoxInjectableModule {
  @preResolve               // <<<<<<<<<<<<< needed for async init
  @lazySingleton
  Future<Store> get store async => await openStore();
}

现在是让它工作的诀窍:我后来的错误是由尚未完成的注入器初始化引起的。将根文件夹中的 injection.dart 更改为 Futureawaitmain() 中调用后,它起作用了。 injection.dart 现在看起来像这样:

final GetIt getIt = GetIt.instance;

@injectableInit
Future<void> configureInjection(String env) async {
  $initGetIt(getIt, environment: env);
}