Search code examples
dartdart-async

How to wait until image(s) loaded in Dart


I have some basic code to load some sprite images, I am using Future.wait to wait until both images are loaded. However this still does not what I exactly want to do, Because I want to assign image width and height to members before It exits.

SpaceShip(this.x, this.y) {
  rocket = new ImageElement(src: "nofire.png");
  firingRockets = new ImageElement(src: "fire.png");
  var futures = [rocket.onLoad.first, firingRockets.onLoad.first];
  Future.wait(futures).then((_) {
    width = rocket.width;
    height = rocket.height;
    print("Images loaded. $width $height");     
  });
  print("Returning");
}
....
ship = new SpaceShip(400.0, 200.0);
print("Ship Constructor exited");

The output:

Returning
Ship Constructor exited
Images loaded. 40 75

I want a way to wait until everything image loading done before exiting the constructor.Is there a good way to do this in Dart?


Solution

  • I just added some comments why it doesn't work

    SpaceShip(this.x, this.y) {
      rocket = new ImageElement(src: "nofire.png");
      firingRockets = new ImageElement(src: "fire.png");
      var futures = [rocket.onLoad.first, firingRockets.onLoad.first];
      // this call just gets enqueued in the Dart event queue and then the 
      // execution is continued at the next statement
      // the async code is executed only after this thread of execution 
      // has ended
      Future.wait(futures).then((_) {
        width = rocket.width;
        height = rocket.height;
        print("Images loaded. $width $height");     
      });
      // this code doesn't wait for Future.wait to finish
      print("Returning");
    }
    ....
    // this code doesn't wait for Future.wait to finish
    ship = new SpaceShip(400.0, 200.0);
    print("Ship Constructor exited");
    

    This way it should work (not tested)

    SpaceShip(this.x, this.y);
    
    // I moved this to a method because the constructor can't return a Future
    Future load() {
      rocket = new ImageElement(src: "nofire.png");
      firingRockets = new ImageElement(src: "fire.png");
      var futures = [rocket.onLoad.first, firingRockets.onLoad.first]; 
      return Future.wait(futures).then((_) {  // return a Future
        width = rocket.width;
        height = rocket.height;
        print("Images loaded. $width $height");     
      })
      .then(() {
        print("Returning");
      }});
    }
    ....
    
    var ship = new SpaceShip(400.0, 200.0);
    // the returned future allows to wait until the async code has finished (using then)
    ship.load().then(() {
        print("Ship Constructor exited");
    });