Home > Mobile >  Dart: how do I initialize a class such that one of its properties is filled upon initialization via
Dart: how do I initialize a class such that one of its properties is filled upon initialization via

Time:01-13

I have a file called database.dart. In it, I have a string property called currentUsername. This is the currently logged in user's username. I want this class to call the getUsernameFS() function only once and then be able to reuse this string for the rest of the class's existence inside its other functions. How do I accomplish this?

The code below gives an error: Error: A value of type 'Future<String>' can't be assigned to a variable of type 'String'.

class Database {

  late String currentUsername = getUsernameFS(); //ERROR IS HERE

  Future<String> getUsernameFS() async {...}

  String someFunction() {...//some function that uses currentUsername//...}

}

CodePudding user response:

First of all, create init() method in your class to call getUsername function once.:

 class Database {
  String currentUsername;

  Future<String> getUsernameFS() async {...}

  void init() {
    currentUsername = getUsernameFS();
  }

  String someFunction() {...//some function that uses currentUsername//...}
}

Keep in mind that the getUsernameFS() is returning a Future<String> and you cannot assign it to a variable of type String directly. To fix this use async/await combination:

  void init() async {
    currentUsername = await getUsernameFS();
  }

To handle errors in future:

void init() {
    getUsernameFS().then((username) {
      currentUsername = username;
    }).catchError((e) {
      print(e);
    });
  }

Good luck!

CodePudding user response:

A couple of other options:

  • Make your member variable a Future instead:

    Future<String> currentUsername = getUsernameFS();
    

    This has the advantage of safely avoiding accidental errors from callers who neglect to explicitly call some asynchronous initialization method first. However, this has the disadvantage of forcing all callers to await the result, making them also asynchronous.

  • If possible, make your class constructor private and force callers to obtain instances with an asynchronous, factory-like static method:

    class Database {
      Database._();
    
      static Future<Database> create() async {
        var db = Database._();
        db.currentUsername = await db.getUsernameFS();
        return db;
      }
    
      ...
    }
    

    This also has the advantage of safely avoiding accidental errors, and it avoids forcing all consumers of currentUsername to be asynchronous. A disadvantage is that a private constructor would prevent your class from being extended.

    If possible, I'd also make getUsernameFS a static method and pass the username to the private constructor. Then currentUsername wouldn't need to be late, and you would avoid any risk of accidentally using a late variable before it's initialized.

  • Related