flutter Hive with riverpod box getter always return null

yqyhoc1h  于 2023-06-07  发布在  Flutter
关注(0)|答案(2)|浏览(135)

我创建了一个单例类作为Hive初始化。但是当我在那个类中调用 getter 时,它从来没有返回一个值,而是返回一个错误。我试过用?标记,当我用!标记调用它时,它返回Null check operator used on a null value。还尝试了late,它给予错误LateInitialization

class Takok {
  static final Takok _t = Takok._internal();
  factory Takok() => _t;

  Takok._internal();

  Box<Transaksi>? _boxTransaksi;
  Box<InappProses>? _boxInappProses;

  Future<Takok> akses() async {
    final takok = Takok._internal();
    final direktori = await getApplicationDocumentsDirectory();

    await Hive.initFlutter(direktori.path);
    await takok.init();

    return takok;
  }

  Future<void> init() async {
    Hive.registerAdapter(TransaksiAdapter());
    Hive.registerAdapter(InappProsesAdapter());
    this._boxTransaksi = await Hive.openBox<Transaksi>('transaksi');
    this._boxInappProses = await Hive.openBox<InappProses>('inappproses');
  }

  Box<Transaksi> get boxTransaksi => _boxTransaksi!;
  Box<InappProses> get boxInappProses => _boxInappProses!;
}

当我尝试检查main()函数上的框是否打开时,它返回true。

void main() async {
  await Takok().akses().then((value) {
    [value.boxTransaksi,value.boxInappProses].forEach((element) {
      if (element.isOpen) print('$element is open');
      });
    print('done checking');
  });
}

有人可以帮助或解释如何解决这个问题吗?我想在提供者内部使用(riverpod exactly),例如:

final providerTakok = Provider<Takok>((ref) => Takok());

final providerTakokHelper = ChangeNotifierProvider<TakokHelper>((ref) {
  final db = ref.read(providerTakok);
  final inapp = db.boxInappProses; // <-- this line which give the error
  return TakokHelper(db, inapp);
});

然后我将上述提供者消费给另一个提供者

final providerSplashskrin = Provider((ref) {
  Future.delayed(
    const Duration(seconds: 3),
    () async {
      try {
        final takokHelper = ref.watch(providerTakokHelper);
        print('objection'); // this line was printed if placed above takokHelper
        // ...
      } catch (e) {
        print('error: $e')
      }
    },
  );
});

这是TakokHelper.dart

class TakokHelper extends ChangeNotifier {
  final Takok takok;
  final Box<InappProses> box;
  TakokHelper(this.takok, this.box)

  // ...
}

谢谢你。

7gs2gvoe

7gs2gvoe1#

关键是你不能在回调中使用ref.watch。尝试使用ref.readref.listen
至于你问题的第一部分,你可以使用ProviderContainer来加载你所有的依赖,并将这样一个容器传递给UncontrolledProviderScope。或者在加载值后重写您的提供程序,如下所示:

final storageProvider = Provider((_) => throw UnimplementedError); 

...

// main() async 

final storage = await Hive.initFlutter(direktori.path);

runApp(
  const ProviderScope(
    overrides: [
      storageProvider.overrideWithValue(storage),
    ],
    child: MyApp(),
  ),
);
k97glaaz

k97glaaz2#

经过最后几天的挣扎和困惑,我终于解决了这个问题。配置单元初始化打开配置单元框必须在同一个函数中。所以在 * Takok.dart * 中我合并了akses()init()
Takok.dart

Future<Takok> akses() async {
  final takok = Takok._internal();
  final direktori = await getApplicationDocumentsDirectory();
  await Hive.initFlutter(direktori.path);
    
  Hive.registerAdapter(TransaksiAdapter());
  Hive.registerAdapter(InappProsesAdapter());
  this._boxTransaksi = await Hive.openBox<Transaksi>('transaksi');
  this._boxInappProses = await Hive.openBox<InappProses>('inappproses');

  return takok;
}

相关问题