【问题标题】:How to wait for the future object before proceeding in flutter?如何在继续颤动之前等待未来的对象?
【发布时间】:2019-05-05 14:10:53
【问题描述】:

我正在编写一个使用 SQFlite 数据库的 Flutter 代码。我想从资产中插入图像小部件,并从数据库中获取图像的名称。

    @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Single Line diagram"),backgroundColor: Colors.red.shade700,),
      body: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Align(
          //alignment: Alignment.center,
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: Row(
              //crossAxisAlignment: CrossAxisAlignment.center,
              children: imageList(),
            ),
          ),
        )
      ),
    );
  }

上面的代码调用 imageList() 来显示要显示的图像列表。

List<Widget> imageList(){
    List<Widget> singleLineImages = new List();
    List unit;
    for (int i = 0; i <= widget.unitsList.length-1; i++){
      for (int j = 1; j <= int.parse(widget.unitsList[i].quantity); j++){
        print("${widget.unitsList[i].bulletin}, ${widget.unitsList[i].mountType}, ${widget.unitsList[i].disconnect}");
        getfileName(widget.unitsList[i].bulletin, widget.unitsList[i].mountType, widget.unitsList[i].disconnect);
        //if(fileName != null) {
          singleLineImages.add(
              Image.asset("images/SD_Files_2100/$fileName.jpg", height: 400.0, width: 200.0,));
        //}
      }
    }
    return singleLineImages;
  }

我从使用数据库的 getFileName() 方法获取文件名。

getfileName(String bulletin, String mountType, String disconnect)async {
    fileNameList = await db.getSDfileName(bulletin, disconnect, mountType);
    fileName = fileNameList[0]['FileName'];
    print("filename: $fileName");
  }

现在,在调用 getFileName() 之后,程序不再等待 fileName 并继续进行,它将 filename as null。在 Image.asset 代码之后正确获取文件名。 有什么方法可以让程序等到获得正确的文件名?

【问题讨论】:

  • 使用FutureBuilder 或从initState 调用一个调用异步代码的方法,然后在Future 完成时调用setState() 以使用新值重新构建。 StackOverflow 上有很多类似的问题。 (非常常见的问题)
  • "有什么办法可以让程序等到它得到正确的文件名吗?"不,没有办法等待 Future 完成。 Dart 是单线程的(除非您启动额外的隔离),并且不允许阻塞执行,因为 Future 永远不会完成,因为它也在阻塞的线程上运行。

标签: dart flutter future


【解决方案1】:

开始获取initState() 中的列表并在获取列表时调用setState,以异步方式执行此操作。您可以在下面找到此过程的简化示例。还要注意获取文件名之前的等待语句。这可以确保您在执行完之后返回到那段代码。

class ListPage extends StatefulWidget {
  @override
  _ListPageState createState() => _ListPageState();
}

class _ListPageState extends State<ListPage> {
  // This should actually be a List<MyClass> instead of widgets. 
  List<Widget> _list;

  @override
  void initState() {
    super.initState();
    _fetchList();
  }

  Future _fetchList() async {
    List<Widget> singleLineImages = new List();
    List unit;
    for (int i = 0; i <= widget.unitsList.length-1; i++){
      for (int j = 1; j <= int.parse(widget.unitsList[i].quantity); j++){
        print("${widget.unitsList[i].bulletin}, ${widget.unitsList[i].mountType}, ${widget.unitsList[i].disconnect}");
        String fileName = await getfileName(widget.unitsList[i].bulletin, widget.unitsList[i].mountType, widget.unitsList[i].disconnect);
      singleLineImages.add(
          Image.asset("images/SD_Files_2100/$fileName.jpg", height: 400.0, width: 200.0,));
      }
    }

    // call setState here to set the actual list of items and rebuild the widget.
    setState(() {
      _list = singleLineImages;
    });
  }

  @override
  Widget build(BuildContext context) {
    // Build the list, or for example a CircularProcessIndicator if it is null.
  }
}

旁注:您正在对数据库进行大量调用,这可能效率低下。尝试在单个 db 调用中获取所需的数据。但这是另一个话题。

【讨论】:

    【解决方案2】:

    在课堂上保留Future&lt;Widget&gt; _list; 字段。

    initState() 函数中添加_list = _fetchList();。 还要注意_fetchList 在这种情况下应该返回Future&lt;Widget&gt;。 在你的构建函数中使用FutureBuilder

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多