Search code examples
flutterdartnosqlblocsembast

Flutter + Sembast + streams + cubits


I'm trying to make a simple application that sends/receives SMS and stores data in noSQL database. As small database I chose sembast.

Then some issues emerged.

  1. Pretty much all examples are for old version of flutter, so null-safety prevents from getting working sample of app. After spending a day of useless efforts to make code proper I found another example.
  2. On author's github page there is a working sample, but it is written in a manner when stream is fed directly to UI. By all means I would like to retain data layer abstraction by using cubits of bloc architecture.

It would be not that much of a deal to figure out how to forward streams via cubit->emit calls, but this piece of code made me a bit puzzled:

Future<void> init({required String packageName}) async {


WidgetsFlutterBinding.ensureInitialized();
  platformInit();
  // For dev, find the proper sqlite3.dll
  if (!kIsWeb) {
    sqflite.sqfliteWindowsFfiInit();
  }
  var databaseFactory = getDatabaseFactory(packageName: packageName);
    
  noteProvider = DbNoteProvider(databaseFactory);
  // devPrint('/notepad Starting');
  await noteProvider.ready;
  runApp(MyApp());
}

Core problem is that I can't figure out where this getDatabaseFactory method comes from and in my app it simply gives Method not found: 'getDatabaseFactory'.

Only thing I managed to find on topic is mention of this method for Java on some database.

On the other hand cloning and running (flutter run) initial notebook example runs ok. When I try to dump results of getDatabaseFactory it gives me Instance of 'DatabaseFactoryWeb'.

The questions are:

  1. Is there an easy way to fix this getDatabaseFactory? Maybe I miss dependency?
  2. Is there a way to simplify whole note_provider? It seems a bit overcomplicated.
  3. It would be great if you have a tip how to make not_provider work via bloc architecture. For now plan is to listen to onNotes Stream and on event emit list of "notes" for UI to redraw widget.

Thank you in advance.


Solution

  • Disclaimer: I'm the author of sembast and the example

    I don't blame you, the documentation is poor...I might not answer all your questions though.

    Some explanation

    A factory is a concept I mainly got from the java world. It becomes the main entry point to the library, i.e. a sembast DatabaseFactory allows you to open and delete a database.

    Typically you would use a single factory in your application depending on the target (mobile, web, desktop), the factory might be different.

    By default sembast has a databaseFactoryMemory which does not persists data and a basic databaseFactoryIo implemented on top of a file system (mobile, desktop, DartVM) using a basic json file implementation (which is not cross process safe, i.e. if 2 applications write on the same database, you might loose data).

    Obviously this does not work with persistence on the web, so the package sembast_web exposes databaseFactoryWeb that works on top of indexed_db and that is cross-tab safe.

    On IO application (flutter web/mobile, DartVM), my recommendation is to use sembast_sqflite which implements sembast on top of sqflite which is cross process safe (i.e. no corruption).

    The flutter git project tekartik_app_sembast proposes any opiniated implementation for a getting the proper factory on all platforms using a getDatabaseFactory() exported method (i.e. it will use sembast_web on the web, and sembast_sqflite for Mobile/Desktop). The implementation is available as an example, you might decide for a different database location on the desktop using path_provider package.

    Some responses

    1. Is there an easy way to fix this getDatabaseFactory? Maybe I miss dependency?

    It is a git dependency as declared in the example pubspec, that I explained above, available as a reference here: https://github.com/tekartik/app_flutter_utils.dart/tree/master/app_sembast

    1. Is there a way to simplify whole note_provider? It seems a bit overcomplicated.

    This is just an opniated example. Typically I abstract the database interface to allow switching to a different implementation. But well you can see sembast guide for reading and writing data.

    1. It would be great if you have a tip how to make not_provider work via bloc architecture

    Hard to give an example for all existing architectures (bloc, rxdart, provider). sembast has some similarities with firestore in terms of writing, reading and listening for changes and you might find more example that uses firestore (and at the end you just end up read/writing/listening)