Use ObjectBox / Instantiate store and box with Flutter 2.5 and Riverpod

454

Since you get the ObjectBoxDatabase using the .create method which is a future, you can either use a FutureProvider or overrides

FutureProvider:

final localCoinDatabaseProvider = FutureProvider<ObjectBoxDatabase>((ref) => ObjectBoxDatabase.create());

https://pub.dev/documentation/riverpod/latest/riverpod/FutureProvider-class.html

overrides:

final localCoinDatabaseProvider = Provider<ObjectBoxDatabase>((ref) => throw UnimplementedError());


Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final objectBox = await ObjectBoxDatabase.create();
  runApp(
      const ProviderScope(
        overrides: [localCoinDatabaseProvider.overrideWithValue(objectBox)]
        child: MyApp()
      )
  );
}
Share:
454
Sheitak
Author by

Sheitak

https://www.linkedin.com/in/quentin-moreau-shk/

Updated on November 25, 2022

Comments

  • Sheitak
    Sheitak over 1 year

    I am using ObjectBox on Flutter 2.5 with Riverpod. The goal is to allow fast caching of a lot of data from an API.

    If there is a difference between remote data and that in the box, then we update. The person who no longer has the internet still has good data.

    Has anyone managed to instantiate and best use Objectbox in flutter clean architecture with riverpod ? I found several relevant questions about it here and here. but I can't seem to get anything satisfactory at the moment ...

    If you have any suggestions for doing this. I took into account the update that Objectbox made on their example of store creation.

    The errors are always the same, either the _box or store is not instantiated or else, get null. I would update my post as I research.

    [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field '_box@59089156' has not been initialized.
    
    [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: LateInitializationError: Field 'store' has not been initialized.
    

    ------EDIT 21 oct.2021-----

    Ok, thanks to the help and comments from my colleagues. I update my code to match. No more store or box instantiation problems.

    My code

    abstract class LocalDataSourceRepository<T> {
      Future<Coin?> getCoinById(dynamic id);
      Future<void> addCoin(T object);
    }
    

    The remote / local management is in this implementation, with getRemoteDataCoin which retrieves a full currency from the API and transforms it into an entity

    class CoinRepositoryImpl extends LocalDataSourceRepository {
    
      final CoinRemoteApi _remoteApi;
      final ObjectBoxDatabase _objectBoxDatabase;
    
      CoinRepositoryImpl(
          this._remoteApi,
          this._objectBoxDatabase,
      );
    
      @override
      Future<Coin?> getCoinById(id) async {
        final _box = _objectBoxDatabase.store.box<Coin>();
        final Query<Coin> query = (_boxCoin.query(Coin_.coinId.equals(id))).build();
    
        if (query.findUnique() == null) {
          final coin = await getRemoteDataCoin(id);
          addCoin(coin);
          return query.findUnique();
        } else {
          return query.findUnique();
        }
      }
    
      @override
      Future<void> addCoin(object) async {
        final _box = _objectBoxDatabase.store.box<Coin>();
        _box.put(object);
      }
    
      Future<Coin> getRemoteDataCoin(selectedCoin) async {
        return _remoteApi.getCoinById(
            selectedCoin,
            const CoinRequest(
                localization: 'false',
                tickers: false,
                marketData: false,
                communityData: true,
                developerData: false,
                sparkline: false
            )
        ).then(
              (value) => value.toEntity(),
        );
      }
    }
    
    class ObjectBoxDatabase {
      late final Store store;
      late final Box<Coin> _box;
    
      ObjectBoxDatabase._create(this.store) {
         _box = Box<Coin>(store);
      }
    
      static Future<ObjectBoxDatabase> create() async {
        final store = await openStore();
        return ObjectBoxDatabase._create(store);
      }
    }
    

    My Riverpod providers.

    final localCoinDatabaseProvider = Provider<ObjectBoxDatabase>((ref) => throw UnimplementedError());
    final remoteCoinApiProvider = Provider<CoinRemoteApi>((ref) => CoinRemoteApi());
    
    final coinRepositoryProvider = Provider<LocalDataSourceRepository>((ref) => CoinRepositoryImpl(
        ref.read(remoteCoinApiProvider),
        ref.read(localCoinDatabaseProvider)
    ));
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      final objectBox = await ObjectBoxDatabase.create();
      runApp(
          ProviderScope(
              overrides: [
                localCoinDatabaseProvider.overrideWithValue(objectBox)
              ],
              child: const MyApp()
          )
      );
    }
    
    • CoderUni
      CoderUni over 2 years
      I think the error suggests that you didn't open the box before you've accessed it
    • julemand101
      julemand101 over 2 years
      Where are you using the late ObjectBoxDatabase objectBox; variable you define in main?
  • Sheitak
    Sheitak over 2 years
    Thanks for your Ismail hint, that will make things better. I also got a good hint from @julemand101 specifying the empty constructor in the ObjectBoxDatabase class, so I'm going to rectify that and see what it gives us.