代码之家  ›  专栏  ›  技术社区  ›  SteAp

使用rootbundle加载文件

  •  2
  • SteAp  · 技术社区  · 7 年前

    我需要从文件中加载一个字符串。以下代码始终返回空值:

    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部分的flutter:section中添加了这个:

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

    存在文件i10n/de.yaml。

    我知道rootbundle.loadstring()是异步的。因此我附加了then()调用-假设

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

    只有rootbundle.loadstring()返回的未来能够返回值时才会执行。

    实际上,该方法始终返回“@null@”。因此,我添加了print()语句,输出如下:

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

    显然,loadstring()的未来比final print()语句执行得晚。

    问:但是我应该如何强制未来去执行,以便我可以取回它的价值呢?

    换言之:如何在某些代码中包装一些异步内容,以便立即检索其值?

    PS:颤振/飞镖的第一天。可能是个小问题…

    1 回复  |  直到 7 年前
        1
  •  0
  •   Richard Heap    7 年前

    这个 .then() 正在被执行,但是 之后 身体的其他部分。正如你所说 loadString() 返回一个未来,因此在未来完成。等待未来完成使用 await . (请注意,当您将函数标记为Async时,函数现在必须返回一个未来本身-因为它必须等待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';
      }
    }
    

    你的很多实用功能都变成了 async 由于必须等待一些事情(有很多等待-等待文件读取、HTTP请求完成等)。你最终会以某种方式(从 initState )

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

    当i18nstuff准备就绪时,设置小部件的状态,而构建中包含此内容的小部件将在虚拟UI之间切换几毫秒,直到它准备就绪,然后再切换到实际UI。

    Widget build() {
      if (i18nStuff == null) {
        return new Container();
      }
    
      return new Column(
          // build the real UI here
          );
    }