使用rootBundle加载文件

我需要从文件中加载一个字符串 . 以下代码始终返回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;

  }

我已将此添加到了颤动:pupspec.yaml部分中的部分:

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

文件i10n / de.yaml存在 .

我知道,rootBundle.loadString()是异步的 . 因此,我附加了then()调用 - 假设

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

只有在rootBundle.loadString()返回的Future能够返回值时才会执行 .

实际上,该方法总是返回'@ null @' . 因此,我添加了print()语句,输出:

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

好的,显然loadString()的未来比最终的print()语句执行得晚 .

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:扑扑/飞镖的第一天 . 可能是一个微不足道的问题......

回答(1)

3 years ago

.then() 正在执行,但在身体的其余部分之后 . 正如你所提到的 loadString() 返回一个Future,所以将来会完成 . 等待Future完成使用 await . (请注意,当您将函数标记为异步时,该函数现在必须返回Future本身 - 因为它必须等待loadString在将来完成,因此它本身必须在将来完成...)当您调用 l('something') 时你将不得不等待结果 .

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';
  }
}

由于不得不等待事情,很多你的实用功能变得很重要(最终会出现类似的东西(从 initState 调用)

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

在i18nStuff准备就绪时设置你的Widget的状态,以及在它的构建中有一个Widget,它在虚拟ui之间切换几毫秒直到它准备好,然后是真实的UI .

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

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