2
votes

I need to load a string from a file. The following code always returns null:

static String  l( String name ) {

    String contents;

    rootBundle
     .loadString( 'i10n/de.yaml' )
     .then( (String r)  { contents = 'found'; print( 'then()' ); })
     .catchError( (e) { contents =  '@Error@'; print( 'catchError()' );  })
     .whenComplete(() { contents = 'dd'; print( 'whenComplete()' );  })
     ;

    print( 'after' );

    if ( null == contents ) {
      return '@null@';
    }

    String doc = loadYaml( contents );

    return doc;

  }

I have added this to the flutter: section in pupspec.yaml section:

  assets:
    - i10n/de.yaml
    - i10n/en.yaml

The file i10n/de.yaml exists.

I'm aware, that rootBundle.loadString() is async. Therefore I appended the then() call - assuming that

(String r)  { contents = 'found'; }

only gets executed if the Future returned by rootBundle.loadString() is able to return a value.

Actually, the method always returns '@null@'. Therefore, I added the print() statements, which output this:

I/flutter (22382): after
I/flutter (22382): then()
I/flutter (22382): whenComplete()

OK, obviously the future of loadString() executes later than the final print() statement.

Q: But how do I force the future to execute, so that I may retrieve its value?

In other words: How do I wrap some async stuff in certain code to retrieve its value immediately?

PS: First day of flutter/dart. Probably a trivial question...

1

1 Answers

0
votes

the .then() is getting executed, but after the rest of the body. As you mention loadString() returns a Future, so completes in the future. To wait for a Future to complete use await. (Note that when you mark the function as async, the function must now return a Future itself - as it has to wait for loadString to complete in the future, so it itself has to complete in the future...) When you call l('something') you will have to await the result.

Future<String> l(String name) async {
  try {
    String contents = await rootBundle.loadString('i10n/de.yaml');

    return contents == null ? '@null@' : loadYaml(contents);
  } catch (e) {
    return 'oops $e';
  }
}

It's no big deal that lots of your utility functions become async as a result of having to wait for things (there's a lot of waiting - for files to read, http requests to complete, etc). You'll eventually end up at the top with something like (call this from initState)

refresh(String s) {
  l(s).then((r) {
    setState(() {
      i18nStuff = r;
    });
  });
}

to set the state of your Widget when the i18nStuff is ready, and a Widget that has this in its build to switch between a dummy ui for the few milliseconds until it's ready, and then the real UI.

Widget build() {
  if (i18nStuff == null) {
    return new Container();
  }

  return new Column(
      // build the real UI here
      );
}