Krzysztof
Krzysztof

Reputation: 2082

How to stop execution until future is completed

Context

I have main method:

void main() {
  setupBeforeRun();   // <--- this is important
  runApp(const App());
}


void setupBeforeRun() {
  DependencyInjection.configure(); // <--- here I set up DB object
  DependencyInjection.get<DictionaryService>().getDictionaries(); // <-- here I am using it
}

in DependencyInjection I just create Storage instance:


class StorageService {
  late Database _db;

  StorageService() {
    var future = initDb().then((value) => _db = value);
  }

  Future<Database> initDb() async {
    if (Platform.isWindows || Platform.isLinux) {
      sqfliteFfiInit();
      databaseFactory = databaseFactoryFfi;
    }

    return openDatabase(
      join(await getDatabasesPath(), 'my.db'),
      onCreate: (db, version) => _createTables(db, version),
      version: 1,
    );
  }

Challenge

I want to stop my app until _db is properly initialised. Otherwise I randomly received error Field '_db@24081564 has not been initialized. I'm using async here because openDatabase is async.

What not work

bool isNotComplited = true
var future = initDb().then((value) => _db = value).whenComplited(isNotComplited = false);

while(isNotComplited){}

It just hang all app and future is never completed.

Question

How to wait for future till its complete and then continue? I don't care about latency of waiting , initialised db is more important for me. Above code is just an example. I want to know how to stop and wait for future to complete in synchronous function?

Upvotes: 0

Views: 43

Answers (1)

quoci
quoci

Reputation: 3557

I would suggest you to register your StorageService with registerLazySingletonAsync. To do that you have to create an async method, which returns your StorageService.

class StorageService {
  late Database _db;

  // Calling this method will initialize your Database
  // and returns the corresponding StorageService.
  Future<StorageService> init() async {
    _db = await initDb();
  }
}

Now you register your Service with GetIt.

class DependencyInjection {
  static void configure() {
    GetIt.registerLazySingletonAsync<DictionaryService>(
      () => StorageService().init(),
    );
  }
}

You can then retrieve your StorageService by doing the following:

final storageService = await GetIt.getAsync<StorageService>();
final dictionaries = storageService.getDictionaries();

Upvotes: 0

Related Questions