什么是 Future 以及如何使用它? [英] What is a Future and how do I use it?

查看:103
本文介绍了什么是 Future 以及如何使用它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到以下错误:

A value of type 'Future<int>' can't be assigned to a variable of type 'int'

它可能是另一种类型而不是int,但基本上模式是

It might be another type instead of int, but basically the pattern is

A value of type 'Future<T>' can't be assigned to a variable of type 'T'

所以...

  • 什么是未来?
  • 如何获得我想要获得的实际价值?
  • 当我只有一个 Future 时,我用什么小部件来显示我的价值?
  • What exactly is a Future?
  • How do I get the actual value I want to get?
  • What widget do I use to display my value when all I have is a Future<T>?

推荐答案

如果您熟悉 TaskPromiseasync/await 模式,然后你可以直接跳到如何在 Flutter 中使用带有小部件的 Future"部分.

In case you are familiar with Task<T> or Promise<T> and the async/ await pattern, then you can skip right to the "How to use a Future with the widgets in Flutter" section.

好吧,文档 说:

表示延迟计算的对象.

没错.它也有点抽象和干燥.通常,函数会返回结果.依次.该函数被调用、运行并返回它的结果.在此之前,呼叫者等待.某些功能,特别是当它们访问硬件或网络等资源时,需要一点时间来完成.想象一下从 Web 服务器加载的头像图片、从数据库加载的用户数据或从设备内存加载的多种语言的应用程序文本.那可能会很慢.

That is correct. It's also a little abstract and dry. Normally, a function returns a result. Sequentially. The function is called, runs and returns it's result. Until then, the caller waits. Some functions, especially when they access resources like hardware or network, take a little time to do so. Imagine an avatar picture being loaded from a web server, a user's data being loaded from a database or just the texts of the app in multiple languages being loaded from device memory. That might be slow.

默认情况下,大多数应用程序具有单一的控制流.当此流被阻塞时,例如等待需要时间的计算或资源访问,应用程序就会冻结.如果您足够大,您可能会记住这是标准,但在当今世界,这将被视为错误.即使有些事情需要时间,我们也会得到一些动画.一个微调器,一个沙漏,也许是一个进度条.但是,应用程序如何运行并显示动画,但仍然等待结果?答案是:异步操作.在您的代码等待某事时仍在运行的操作.现在编译器如何知道它是否应该真正停止一切并等待结果,还是继续所有后台工作并仅在此实例中等待?好吧,它无法自己解决这个问题.我们必须告诉它.

Most applications by default have a single flow of control. When this flow is blocked, for example by waiting for a computation or resource access that takes time, the application just freezes. You may remember this as standard if you are old enough, but in today's world that would be seen as a bug. Even if something takes time, we get a little animation. A spinner, an hourglass, maybe a progress bar. But how can an application run and show an animation and yet still wait for the result? The answer is: asynchronous operations. Operations that still run while your code waits for something. Now how does the compiler know, whether it should actually stop everything and wait for a result or continue with all the background work and wait only in this instance? Well, it cannot figure that out on it's own. We have to tell it.

这是通过一种称为 .它不是特定于 ,它在许多其他语言中以相同的名称存在.您可以在此处找到有关 Dart 的文档.

This is achieved through a pattern known as async and await. It's not specific to flutter or dart, it exists under the same name in many other languages. You can find the documentation for Dart here.

由于需要一些时间的方法不能立即返回,所以它会在完成后返回传递值的承诺.

Since a method that takes some time cannot return immediately, it will return the promise of delivering a value when it's done.

这就是所谓的未来.因此,从数据库加载数字的承诺将返回 Future 而从互联网搜索返回电影列表的承诺可能返回 Future>;.Future在未来会给你一个 T 的东西.

That is called a Future. So the promise to load a number from the database would return a Future<int> while the promise to return a list of movies from an internet search might return a Future<List<Movie>>. A Future<T> is something that in the future will give you a T.

让我们尝试不同的解释:

Lets try a different explanation:

future 表示异步操作的结果,可以有两种状态:未完成或已完成.

A future represents the result of an asynchronous operation, and can have two states: uncompleted or completed.

很可能,因为您这样做并不是为了好玩,您实际上需要 Future 的结果来在您的应用程序中取得进展.您需要显示数据库中的编号或找到的电影列表.所以你要等待,直到结果出来.这就是 await 的用武之地:

Most likely, as you aren't doing this just for fun, you actually need the results of that Future<T> to progress in your application. You need to display the number from the database or the list of movies found. So you want to wait, until the result is there. This is where await comes in:

Future<List<Movie>> result = loadMoviesFromSearch(input);

// right here, you need the result. So you wait for it:
List<Movie> movies = await result;

但是等等,我们是不是又回到了原点?不是又要等结果了吗?是的,我们确实如此.如果程序没有一些类似于顺序流的东西,它们将是完全混乱的.但关键是使用关键字 await 我们已经告诉编译器,在这一点上,虽然我们想等待结果,但我们不希望我们的应用程序只是冻结.我们希望所有其他正在运行的操作(例如动画)继续.

But wait, haven't we come full circle? Aren't we waiting on the result again? Yes, indeed we are. Programs would be utterly chaotic if they did not have some resemblence of sequential flow. But the point is that using the keyword await we have told the compiler, that at this point, while we want to wait for the result, we do not want our application to just freeze. We want all the other running operations like for example animations to continue.

但是,您只能在本身标记为 async 并返回 Future 的函数中使用 await 关键字.因为当你 await 某些东西时,等待的函数不能再立即返回它们的结果.你只能归还你所拥有的,如果你必须等待它,你必须返回一个稍后交付的承诺.

However, you can only use the awaitkeyword in functions that themselves are marked as async and return a Future<T>. Because when you await something, then the function that is awaiting can no longer return their result immediately. You can only return what you have, if you have to wait for it, you have to return a promise to deliver it later.

Future<Pizza> getPizza() async {
    Future<PizzaBox> delivery = orderPizza();        

    var pizzaBox = await delivery;

    var pizza = pizzaBox.unwrap();
    
    return pizza;   
}

我们的 getPizza 函数必须等待比萨饼,所以不是立即返回 Pizza,它必须返回比萨饼 将在那里的承诺未来.现在,您可以在某处await getPizza 函数.

Our getPizza function has to wait for the pizza, so instead of returning Pizza immediately, it has to return the promise that a pizza will be there in the future. Now you can, in turn, await the getPizza function somewhere.

flutter 中的所有小部件都期望真实值.不是一些稍后会出现的价值的承诺.当按钮需要文本时,它不能使用文本稍后出现的承诺.它需要显示按钮now,所以它需要文本now.

All the widgets in flutter expect real values. Not some promise of a value to come at a later time. When a button needs a text, it cannot use a promise that text will come later. It needs to display the button now, so it needs the text now.

但有时,您所拥有的只是一个Future.这就是 FutureBuilder 的用武之地.你可以在有未来时使用它,在等待时显示一件事(例如进度指示器),并在完成时显示另一件事(例如结果).

But sometimes, all you have is a Future<T>. That is where FutureBuilder comes in. You can use it when you have a future, to display one thing while you are waiting for it (for example a progress indicator) and another thing when it's done (for example the result).

让我们看一下我们的披萨示例.您想订购比萨饼,您在等待时需要进度指示器,您想在交付后查看结果,并且可能在出现错误时显示错误消息:

Let's take a look at our pizza example. You want to order pizza, you want a progress indicator while you wait for it, you want to see the result once it's delivered, and maybe show an error message when there is an error:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

/// ordering a pizza takes 5 seconds and then gives you a pizza salami with extra cheese
Future<String> orderPizza() {
  return Future<String>.delayed(Duration(seconds: 5), () async => 'Pizza Salami, Extra Cheese');
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: Scaffold(
        body: Center(
          child: PizzaOrder(),
        ),
      ),
    );
  }
}

class PizzaOrder extends StatefulWidget {
  @override
  _PizzaOrderState createState() => _PizzaOrderState();
}

class _PizzaOrderState extends State<PizzaOrder> {
  Future<String> delivery;

  @override
  Widget build(BuildContext context) {
    return Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          RaisedButton(
            onPressed: delivery != null ? null : () => setState(() { delivery = orderPizza(); }),
            child: Text('Order Pizza Now')
          ),
          delivery == null
            ? Text('No delivery scheduled')
            : FutureBuilder(
              future: delivery,
              builder: (context, snapshot) {
                if(snapshot.hasData) {
                  return Text('Delivery done: ${snapshot.data}');
                } else if(snapshot.hasError) {
                  return Text('Delivery error: ${snapshot.error.toString()}');
                } else {
                  return CircularProgressIndicator();
                }
              })
        ]);
  }
}

这就是你如何使用 FutureBuilder 来显示你的未来结果.

This is how you use a FutureBuilder to display the result of your future once you have it.

这篇关于什么是 Future 以及如何使用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆