skip to Main Content

I’ve make a singleton class as Hive initialization. But when I call the getter inside that class, it never return a value and returning an error instead. I’ve tried with ? mark, it return Null check operator used on a null value when I call it wit ! marks. Also tried with late and it give error 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!;
}

When I try to check if the box is open on main() function, it returns 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');
  });
}

Anyone can help or explain to me how to fix this? I want to use inside a provider (riverpod exactly), like :

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

Then I consume above provider to another provider

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')
      }
    },
  );
});

And this is TakokHelper.dart

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

  // ...
}

Thank you.

2

Answers


  1. Chosen as BEST ANSWER

    After a last couple of days struggling and confused by my self, I finally fix the issue. The Hive initialization and opening Hive box must be in the same function. So in Takok.dart I merge the akses() and 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;
    }
    

  2. The whole point is that you cannot use ref.watch in callbacks. Try using ref.read or ref.listen.

    As for the first part of your question, you can use ProviderContainer to load all your dependencies in it and pass such a container to UncontrolledProviderScope. Or override your provider after the value is loaded like this:

    final storageProvider = Provider((_) => throw UnimplementedError); 
    
    ...
    
    // main() async 
    
    final storage = await Hive.initFlutter(direktori.path);
    
    runApp(
      const ProviderScope(
        overrides: [
          storageProvider.overrideWithValue(storage),
        ],
        child: MyApp(),
      ),
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search