2

我见过的所有示例都在 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);

然后,这些包创建一个JournalsRemoteDataSourceand of的实例JournalsRemoteDataSource并将其注入到存储库中。

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 或者如果我要初始化(在上游) ,我如何objectBox从注入的对象中访问对象JournalsRemoteDataSourceobjectBoxMyApp()HomePage

PS: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;
}

虽然我不明白吸气剂的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'
4

2 回答 2

1

因此,在另一个徒劳的答案之后,我按如下方式实现了这一点。我的架构遵循 Reso Coder 的 DDD 和 Clean Architecture 教程的合并。基本上它是具有清洁架构的本地/远程数据源层的 DDD。

基础设施目录

抽象数据源

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();

基础设施/核心中的可注入模块

@module
abstract class ObjectBoxInjectableModule {
  @preResolve               // <<<<<<<<<<<<< needed for async init
  @lazySingleton
  Future<Store> get store async => await openStore();
}

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

final GetIt getIt = GetIt.instance;

@injectableInit
Future<void> configureInjection(String env) async {
  $initGetIt(getIt, environment: env);
}
于 2021-08-07T15:31:47.077 回答
0

我没有使用包get_it&的经验injectable,但是从文档中,我认为以下替代方案会起作用。直接使用get_it,不确定使用injectable(generator for get_it) 实现相同效果的正确方法,但我想如果您熟悉它,您可以将其配置为生成相同的代码。

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

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

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

改变你的main东西,比如:

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

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

于 2021-08-06T16:34:32.787 回答