什么是未来,我将如何使用它?

时间:2020-07-21 14:55:10

标签: flutter dart async-await future flutter-futurebuilder

我收到以下错误:

def bar():
    array_1 = [1, 2, 3]
    array_2 = [4, 5, 6]
    array_3 = [7, 8, 9]
    array_4 = [10, 11, 12]
    array_5 = [1, 2, 3]
    scope = locals()
    return [arrays for arrays in combinations([f"array_{i}" for i in range(1,6)],2) 
     if np.all(eval(arrays[0],scope) == eval(arrays[1],scope))]

它可能是另一种类型,而不是A value of type 'Future<int>' can't be assigned to a variable of type 'int' ,但是模式基本上是

int

所以...

  • A value of type 'Future<T>' can't be assigned to a variable of type 'T' 到底是什么?
  • 如何获得想要获得的实际价值?
  • 当我只有Future时,我该使用什么小部件来显示我的价值?

3 个答案:

答案 0 :(得分:8)

如果您熟悉Task<T>Promise<T>async / await模式,则可以直接跳至“如何使用Flutter中的小部件一起使用,未来。”

什么是未来,我将如何使用它?

好吧,documentation说:

代表延迟计算的对象。

是正确的。它也有点抽象和干燥。通常,函数返回结果。依序。该函数将被调用,运行并返回结果。在此之前,呼叫者等待。有些功能,尤其是当它们访问诸如硬件或网络之类的资源时,需要一些时间来完成。想象从网络服务器上加载头像图片,从数据库中加载用户数据,或者仅从设备内存中加载多种语言的应用程序文本。那可能很慢。

默认情况下,大多数应用程序只有一个控制流。当阻止此流时(例如,通过等待耗时的计算或资源访问),应用程序将冻结。如果年龄足够大,您可能会记得这是标准配置,但是在当今世界,这将被视为错误。即使花费一些时间,我们也会获得一些动画效果。一个微调器,一个沙漏,或者一个进度条。但是,应用程序如何运行并显示动画却仍然等待结果?答案是:异步操作。代码等待某些操作时仍在运行的操作。现在,编译器如何知道是应该停止所有操作并等待结果,还是继续所有后台工作并仅在这种情况下等待?好吧,它自己不能弄清楚。我们必须告诉

这是通过称为的模式来实现的。它不特定于,它在许多其他语言中以相同的名称存在。您可以找到Dart here的文档。

由于花费一些时间的方法无法立即返回,因此它将返回完成时传递值的承诺。

这称为Future。因此,从数据库中加载数字的承诺会返回Future<int>,而从互联网搜索中返回电影列表的承诺可能会返回Future<List<Movie>>Future<T>是将来 会给您的T

让我们尝试不同的解释:

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

最有可能的是,因为您并不是仅仅出于娱乐目的,所以实际上您需要该Future<T>的结果才能在应用程序中进行。您需要显示数据库中的号码或找到的电影列表。因此,您要等待,直到结果出现为止。这是await出现的地方:

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

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

但是,等等,我们还没来回吗?我们不是又在等待结果吗?是的,确实如此。如果程序与顺序流没有某种相似之处,它们将完全混乱。但是,要点是,使用关键字await告诉编译器,这时,尽管我们要等待结果,但我们不希望应用程序冻结。我们希望所有其他正在运行的操作(例如动画)继续进行。

但是,您只能在本身被标记为await的函数中使用async关键字并返回一个Future<T>。因为当您await进行某些操作时,正在等待的函数不再能够立即返回其结果。您只能退还所拥有的东西,如果您必须等待,则必须退还保证书,以便以后交付。

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

    var pizzaBox = await delivery;

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

我们的getPizza函数必须等待来获得披萨,因此与其立即返回Pizza,还必须返回一个承诺,即将来会出现披萨 < / em>。现在,您可以依次在某处await getPizza函数。

如何在Flutter中将Future与窗口小部件一起使用?

扑朔迷离的所有小部件都期望真实值。将来没有价值的承诺。当按钮需要文本时,它不能使用稍后会出现文本的承诺。它需要显示按钮 now ,所以它需要文本 now

但是有时候,您只有Future<T>。这就是FutureBuilder进入的地方。您可以在有未来时使用它,在等待时显示一件事(例如进度指示器),在完成时显示另一件事(例如结果)

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

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来显示未来结果的方式。

答案 1 :(得分:2)

Future<T>返回将由async工作完成的潜在值

例如:

Future<int> getValue() async {
    return Future.value(5);
  }

以上代码返回的是Future.value(5)类型的int,但是在从方法中接收值时,我们不能使用类型Future<int>,即

Future<int> value = await getValue();  // Not Allowed
// Error
A value of type 'Future<int>' can't be assigned to a variable of type 'int'

要解决上述问题,应在int类型下接收getValue()

  int value = await getValue(); // right way as it returning the potential value. 

答案 2 :(得分:1)

以下是来自其他语言的 Dart Future 类比列表:

  • JS:Promise
  • Java:Future
  • 派顿:Future
  • C#:Task

就像在其他语言中一样,Future 是一种特殊类型的对象,它允许使用 async/await 语法糖,以同步/线性方式编写异步代码。您从异步方法返回 Future 而不是接受回调作为参数并避免回调地狱 - Futures 和回调都解决了相同的问题(稍后触发一些代码),但方式不同。