Magnus
Magnus

Reputation: 18810

How can I await a variable

Is it possible to use a Future to await a change of value of a simple variable in Dart?

In my case, I have a singleton method that, upon the first call, creates and opens a database. This method is being called from multiple places in my app, and I need a way for the second, third, etc. calls to wait until the first call has created and opened the database.

class DB{
    static Database _db;

    static Future<Database> instance() async {
        if( _db == null ){
            print('Creating/opening database');
            _db = await createOrOpenDatabase();
        }            

        return _db;
    }
}

// Somewhere in the app
await DB.instance().doSomething();


// Meanwhile, somewhere else in the app
await DB.instance().doSomethingElse();

This results in

Creating/opening database
Creating/opening database

One way to solve this would be to add some variable that indicates that the database is currently being created and/or opened:

class DB{
    static Database _db;
    static bool _openingDb;

    static Database instance() async {
        if( _openingDb )
            // Wait until _openingDb becomes false

        if( _db == null ){
            _openingDb = true;
            print('Creating/opening database');
            _db = await createOrOpenDatabase();
            _openingDb = false;
        }            

        return _db;
    }
}

But just how do I wait for the value of _openingDb to change? It seems like I'm missing something obvious here...

Upvotes: 1

Views: 55

Answers (1)

Magnus
Magnus

Reputation: 18810

I figured out that I can use a Completer to accomplish what I wanted.

class DB {
    static Database _db;
    static Completer _dbOpenCompleter;

    static Future<Database> instance() async {
        if( _dbOpenCompleter != null && !_dbOpenCompleter.isCompleted ) {
            print('Awaiting database creation');        
            await _dbOpenCompleter.future;
        }

        if( _db == null ) {
            _dbOpenCompleter = Completer();
            try {
                print('Creating/opening database');            
                _db = await openOrCreateDatabase();
            }
            finally{
                _dbOpenCompleter.complete();
            }
        }

        return _db;
    }
}

Now the same calls as in the original question result in the following output:

Creating/opening database
Awaiting database creation

Upvotes: 3

Related Questions