【问题标题】:how to assign future<> to widget in flutter?如何将future<>分配给flutter中的小部件?
【发布时间】:2018-09-20 17:43:43
【问题描述】:

假设我有一个SingleChildScrollView,它的内容是从一个文件中读取的:

singleChildScrollView(
        padding: EdgeInsets.all(8.0),
        child: nw Text(
          getTextFromFile(), //<---read from file
          style: TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 19.0,
          ),
        ));

  Future<String> getFileData(String path) async {
    return await rootBundle.loadString(path);
  }

  Future<String> getTextFromFile() async {
      return getFileData("test.txt");
  }

我收到以下错误:

The argument type 'Future<String>' can't be assigned to the parameter
type 'String'.

如何解决这个问题?

【问题讨论】:

  • 你可能需要一个 FutureBuilder。
  • 我认为 FutureBuilder 的答案应该是选择的那个。更简单,由 Flutter 推荐。

标签: dart flutter


【解决方案1】:

使用 FutureBuilder 应该可以解决您的问题。我修改了您的代码,以便您了解如何使用它。 initialData 不是必需的。

  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: getTextFromFile(),
      initialData: "Loading text..",
      builder: (BuildContext context, AsyncSnapshot<String> text) {
        return new SingleChildScrollView(
          padding: new EdgeInsets.all(8.0),
          child: new Text(
            text.data,
            style: new TextStyle(
              fontWeight: FontWeight.bold,
              fontSize: 19.0,
            ),
          ));
      });
  }

  Future<String> getFileData(String path) async {
    return await new Future(() => "test text");
  }

  Future<String> getTextFromFile() async {
    return getFileData("test.txt");
  }
}

【讨论】:

  • 但是这种方法太大了,无法完成简单的事情
  • @Bensal 我不这么认为,如果你看得很清楚,它只是返回后的前四行代码,因为答案包括完整组件的实现细节。我认为如果您的计划是在组件中使用未来响应,那真是太棒了。在四行代码中,我可以完全控制异步事物。无需尝试、捕捉或捕捉复杂情况,只需一段简单的代码
  • 我相信这是正确的方法,应该是公认的答案。 Future 和 Stream 是 Dart 的一些最突出的特性,flutter 让 FutureBuilder 和 StreamBuilder 可以处理这种数据类型。在使用 Flutter 时,我会避免使用 .then() 方法。
  • 很惊讶这不是公认的答案。
【解决方案2】:

StatefulWidget 可用于此目的。 声明成员变量String _textFromFile = "";在您的 State 类中,并使用 setState() 方法在未来解析时更新其值。

我从构造函数中调用了您的 getTextFromFile() 方法,但您可以从任何地方调用它。

运行代码:

import 'package:flutter/material.dart';
import 'dart:async';

class StatefullWidgetDemo extends StatefulWidget {
  @override
  _StatefulWidgetDemoState createState() {
    return new _StatefulWidgetDemoState();
  }
}

class _StatefulWidgetDemoState extends State<StatefullWidgetDemo> {
  String _textFromFile = "";

  _StatefulWidgetDemoState() {
    getTextFromFile().then((val) => setState(() {
          _textFromFile = val;
        }));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Stateful Demo'),
      ),
      body: new SingleChildScrollView(
        padding: new EdgeInsets.all(8.0),
        child: new Text(
          _textFromFile,
          style: new TextStyle(
            fontWeight: FontWeight.bold,
            fontSize: 19.0,
          ),
        ),
      ),
    );
  }

  Future<String> getFileData(String path) async {
    return "your data from file";
  }

  Future<String> getTextFromFile() async {
    return await getFileData("test.txt");
  }
}

【讨论】:

  • 这看起来更直观,所以我将其标记为已接受。我也喜欢Doge的答案,所以我投票。
【解决方案3】:

这里简单回答=>

调用函数的类:

@override
Widget build(BuildContext context) {
return new Scaffold(
 child: FutureBuilder(
  future: function(),
  builder: (BuildContext context, AsyncSnapshot<String> text) {
    return new Text(text.data);
  });
)}

以及功能:

Future<String> function() async {
   return 'abc';
}

【讨论】:

    【解决方案4】:

    这是一个类似的问题:

    flutter / dart error: The argument type 'Future<File>' can't be assigned to the parameter type 'File'

    那里提出的解决方案非常优雅并且可以正常工作。如果 IDE 表示它需要 Type 而不是 Future&lt;Type&gt;,则将 await 放在该参数前面

    【讨论】:

      【解决方案5】:

      获取初始化数据的另一种解决方案是在initState() 中调用getTextFromFile(),使用新字符串设置状态并在小部件中使用该字符串:

      String fileData = '';
      
      Future<String> getFileData(String path) async {
          return await rootBundle.loadString(path);
        }
      
      void getTextFromFile() async {
          try {
            String data = await getFileData("test.txt");
            setState(() {
              fileData = data;
            });
          } catch (ex) {
            print(ex);
          }
        }
      
        @override
        void initState() {
          super.initState();
          getTextFromFile();
        }
      
      new singleChildScrollView(
              padding: new EdgeInsets.all(8.0),
              child: new Text(
                fileData,
                style: new TextStyle(
                  fontWeight: FontWeight.bold,
                  fontSize: 19.0,
                ),
              ));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-23
        • 1970-01-01
        • 2021-05-20
        • 1970-01-01
        • 1970-01-01
        • 2021-02-26
        • 1970-01-01
        相关资源
        最近更新 更多