出现以下错误:
A value of type 'Future<int>' can't be assigned to a variable of type 'int'
它可能是int之外的另一种类型,但基本上模式是:
int
A value of type 'Future<T>' can't be assigned to a variable of type 'T'
因此:
Future
Future<T>
qvtsj1bj1#
如果您熟悉Task<T>或Promise<T>以及async/await模式,那么您可以直接跳到“如何使用Future和Flutter中的小部件”部分。
Task<T>
Promise<T>
async
await
documentation表示:对象,表示延迟的计算。没错。它也有点抽象和枯燥。通常,一个函数返回一个结果。按顺序。函数被调用、运行并返回它的结果。在此之前,调用者会等待。有些函数,尤其是当它们访问硬件或网络等资源时,需要一点时间来完成。想象一下,一个头像图片从Web服务器加载,从数据库加载用户数据,或者只是从设备内存加载应用程序的多语言文本,这可能会很慢。默认情况下,大多数应用程序都有一个控制流。当这个控制流被阻塞时,例如,等待一个需要花费时间的计算或资源访问时,应用程序就会冻结。如果你足够大,你可能会记得这是一个标准的控制流,但在今天的世界里,这会被视为一个bug。即使某个东西需要时间,我们也会得到一个小动画。一个旋转器,一个沙漏,也许是一个进度条。2但是一个应用程序如何运行并显示一个动画,同时还在等待结果呢?3答案是:异步操作。当你的代码等待某个东西的时候,这些操作仍然在运行。现在编译器怎么知道,它是应该停止一切并等待一个结果,还是继续所有的后台工作并只在这个示例中等待?嗯,它自己无法判断出这一点。我们必须告诉它。这是通过一种称为async和await的模式来实现的。它并不特定于flutter或dart,它在许多其他语言中以相同的名称存在。您可以找到Dart here的文档。由于一个需要一些时间的方法不能立即返回,它将返回一个在完成时传递值的承诺。这被称为Future,因此,从数据库加载一个数字的承诺将返回Future<int>,而从互联网搜索返回一个电影列表的承诺可能返回Future<List<Movie>>,Future<T>是 * 在未来 * 会给你T的东西。让我们尝试一种不同的解释:future表示异步操作的结果,可以有两种状态:未完成的或完成的。很有可能,你并不是为了好玩才这么做的,你实际上需要Future<T>的结果来推进你的应用程序。你需要显示数据库中的数字或者找到的电影列表。所以你想等待,直到结果出现。这就是await的用武之地:
Future<int>
Future<List<Movie>>
T
Future<List<Movie>> result = loadMoviesFromSearch(input); // right here, you need the result. So you wait for it: List<Movie> movies = await result;
但是等等,我们不是又回到原点了吗?我们不是又在等待结果了吗?是的,我们确实是在等待。如果程序没有一些类似于顺序流的东西,程序会完全混乱。但关键是,使用关键字await,我们已经告诉编译器,在这一点上,当我们想等待结果时,我们不希望我们的应用程序只是冻结。2我们希望所有其他运行的操作,例如动画继续。但是,你只能在本身标记为async的函数中使用await关键字,并返回Future<T>。因为当你await某个东西时,等待的函数就不能再立即返回它们的结果了。你只能返回你所拥有的,如果你必须等待它,你就必须返回一个稍后交付它的承诺。
Future<Pizza> getPizza() async { Future<PizzaBox> delivery = orderPizza(); var pizzaBox = await delivery; var pizza = pizzaBox.unwrap(); return pizza; }
我们的getPizza函数必须 * 等待 * 比萨饼,因此它必须返回比萨饼 * 将来会出现 * 的承诺,而不是立即返回Pizza。现在,您可以在某处依次执行await getPizza函数。
Pizza
flutter中的所有小部件都期望得到真实的值,而不是一个以后会出现的值的承诺,当一个按钮需要一个文本时,它不能使用一个以后会出现文本的承诺,它需要显示按钮 now,所以它需要文本 now。但有时候,你所拥有的只是一个Future<T>。这就是FutureBuilder的用武之地。当你有一个未来时,你可以使用它,在你等待它的时候显示一件事(例如进度指示器),在它完成的时候显示另一件事(例如结果)。让我们看一下我们的比萨饼示例。您希望订购比萨饼,希望在等待过程中显示进度指示器,希望在发送后看到结果,并且可能在出现错误时显示错误消息:
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(const 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: [ ElevatedButton( onPressed: delivery != null ? null : () => setState(() { delivery = orderPizza(); }), child: const Text('Order Pizza Now') ), delivery == null ? const 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 const CircularProgressIndicator(); } }) ]); } }
这就是你如何使用FutureBuilder来显示你未来的结果。
ttygqcqt2#
下面是其他语言中与Dart的Future的类比列表:
Promise
Task
就像其他语言一样,Future是一种特殊类型的对象,允许使用async/await语法sugar,以同步/线性方式编写异步代码。您可以从async方法返回Future,而不是接受回调作为参数,从而避免回调地狱-Future和回调都解决了相同的问题(在稍后的时间触发一些代码),但方式不同。
e0bqpujr3#
Future<T>返回将由async完成的工作的电位值例如:
Future<int> getValue() async { return Future.value(5); }
上面的代码返回int类型的Future.value(5),但是当从方法接收值时,我们不能使用Future<int>类型,即
Future.value(5)
Future<int> value = await getValue(); // Not Allowed // Error A value of type 'Future<int>' can't be assigned to a variable of type 'int'
要解决上面的getValue()应该在int类型下接收
int value = await getValue(); // right way as it returning the potential value.
erhoui1w4#
我希望这一要点能提供一些信息,我将以两种不同的异步方法进行演示:
请注意以下方法,其中showLoading()、getAllCarsFromApi()和hideLoading()是内部Async方法。如果我将await关键字放在showLoading()之前,Operation会等待它完成,然后转到下一行,但我有意删除了await,因为我需要在处理getAllCarsFromApi()的同时显示Loading对话框,因此这意味着showLoading()和getAllCarsFromApi()方法在不同的线程上处理。最后hideLoading()隐藏了加载对话框。
showLoading()
getAllCarsFromApi()
hideLoading()
Async
Future<List<Car>> getData() async{ showLoading(); final List<Car> cars = await getAllCarsFromApi(); hideLoading(); return cars; }
现在看另一个Async方法,这里getCarByIdFromApi()方法需要一个id,它是从getCarIdFromDatabase()计算出来的,因此在第一个方法之前必须有一个await关键字,以使Operation等待,直到计算出id并将其传递给第二个方法。因此,这里的两个方法是在单个Thread中依次处理的。
getCarByIdFromApi()
id
getCarIdFromDatabase()
Future<Car> getCar() async{ int id = await getCarIdFromDatabase(); final Car car = await getCarByIdFromApi(id); return car; }
bmp9r5qi5#
一个简单的答案是,如果一个函数返回它的值时带有一个delay,那么Future就被用来获取它的值。
delay
Future<int> calculate({required int val1, required int val2}) async { await Future.delayed(const Duration(seconds: 2)); return val1 + val2; }
如果我们调用上面的函数
getTotal() async { int result = calculate(val1: 5, val2: 5); print(result); }
我们将得到以下错误:
但是如果我们在函数调用之前使用await,它将在延迟之后给出函数的实际返回值
getTotal() async { int result = await calculate(val1: 5, val2: 5); print(result); }
使用await for the Future获取返回值需要关键字async
5条答案
按热度按时间qvtsj1bj1#
如果您熟悉
Task<T>
或Promise<T>
以及async
/await
模式,那么您可以直接跳到“如何使用Future和Flutter中的小部件”部分。什么是未来,我该如何利用它?
documentation表示:
对象,表示延迟的计算。
没错。它也有点抽象和枯燥。通常,一个函数返回一个结果。按顺序。函数被调用、运行并返回它的结果。在此之前,调用者会等待。有些函数,尤其是当它们访问硬件或网络等资源时,需要一点时间来完成。想象一下,一个头像图片从Web服务器加载,从数据库加载用户数据,或者只是从设备内存加载应用程序的多语言文本,这可能会很慢。
默认情况下,大多数应用程序都有一个控制流。当这个控制流被阻塞时,例如,等待一个需要花费时间的计算或资源访问时,应用程序就会冻结。如果你足够大,你可能会记得这是一个标准的控制流,但在今天的世界里,这会被视为一个bug。即使某个东西需要时间,我们也会得到一个小动画。一个旋转器,一个沙漏,也许是一个进度条。2但是一个应用程序如何运行并显示一个动画,同时还在等待结果呢?3答案是:异步操作。当你的代码等待某个东西的时候,这些操作仍然在运行。现在编译器怎么知道,它是应该停止一切并等待一个结果,还是继续所有的后台工作并只在这个示例中等待?嗯,它自己无法判断出这一点。我们必须告诉它。
这是通过一种称为async和await的模式来实现的。它并不特定于flutter或dart,它在许多其他语言中以相同的名称存在。您可以找到Dart here的文档。
由于一个需要一些时间的方法不能立即返回,它将返回一个在完成时传递值的承诺。
这被称为
Future
,因此,从数据库加载一个数字的承诺将返回Future<int>
,而从互联网搜索返回一个电影列表的承诺可能返回Future<List<Movie>>
,Future<T>
是 * 在未来 * 会给你T
的东西。让我们尝试一种不同的解释:
future表示异步操作的结果,可以有两种状态:未完成的或完成的。
很有可能,你并不是为了好玩才这么做的,你实际上需要
Future<T>
的结果来推进你的应用程序。你需要显示数据库中的数字或者找到的电影列表。所以你想等待,直到结果出现。这就是await
的用武之地:但是等等,我们不是又回到原点了吗?我们不是又在等待结果了吗?是的,我们确实是在等待。如果程序没有一些类似于顺序流的东西,程序会完全混乱。但关键是,使用关键字
await
,我们已经告诉编译器,在这一点上,当我们想等待结果时,我们不希望我们的应用程序只是冻结。2我们希望所有其他运行的操作,例如动画继续。但是,你只能在本身标记为
async
的函数中使用await
关键字,并返回Future<T>
。因为当你await
某个东西时,等待的函数就不能再立即返回它们的结果了。你只能返回你所拥有的,如果你必须等待它,你就必须返回一个稍后交付它的承诺。我们的getPizza函数必须 * 等待 * 比萨饼,因此它必须返回比萨饼 * 将来会出现 * 的承诺,而不是立即返回
Pizza
。现在,您可以在某处依次执行await
getPizza函数。如何在Flutter中使用Future和小部件?
flutter中的所有小部件都期望得到真实的值,而不是一个以后会出现的值的承诺,当一个按钮需要一个文本时,它不能使用一个以后会出现文本的承诺,它需要显示按钮 now,所以它需要文本 now。
但有时候,你所拥有的只是一个
Future<T>
。这就是FutureBuilder
的用武之地。当你有一个未来时,你可以使用它,在你等待它的时候显示一件事(例如进度指示器),在它完成的时候显示另一件事(例如结果)。让我们看一下我们的比萨饼示例。您希望订购比萨饼,希望在等待过程中显示进度指示器,希望在发送后看到结果,并且可能在出现错误时显示错误消息:
这就是你如何使用FutureBuilder来显示你未来的结果。
ttygqcqt2#
下面是其他语言中与Dart的
Future
的类比列表:Promise
Future
Future
Task
就像其他语言一样,Future是一种特殊类型的对象,允许使用async/await语法sugar,以同步/线性方式编写异步代码。您可以从async方法返回Future,而不是接受回调作为参数,从而避免回调地狱-Future和回调都解决了相同的问题(在稍后的时间触发一些代码),但方式不同。
e0bqpujr3#
Future<T>
返回将由async
完成的工作的电位值例如:
上面的代码返回
int
类型的Future.value(5)
,但是当从方法接收值时,我们不能使用Future<int>
类型,即要解决上面的getValue()应该在
int
类型下接收erhoui1w4#
我希望这一要点能提供一些信息,我将以两种不同的异步方法进行演示:
请注意以下方法,其中
showLoading()
、getAllCarsFromApi()
和hideLoading()
是内部Async
方法。如果我将
await
关键字放在showLoading()
之前,Operation会等待它完成,然后转到下一行,但我有意删除了await
,因为我需要在处理getAllCarsFromApi()
的同时显示Loading对话框,因此这意味着showLoading()
和getAllCarsFromApi()
方法在不同的线程上处理。最后hideLoading()
隐藏了加载对话框。现在看另一个
Async
方法,这里getCarByIdFromApi()
方法需要一个id
,它是从getCarIdFromDatabase()
计算出来的,因此在第一个方法之前必须有一个await
关键字,以使Operation等待,直到计算出id
并将其传递给第二个方法。因此,这里的两个方法是在单个Thread中依次处理的。bmp9r5qi5#
一个简单的答案是,如果一个函数返回它的值时带有一个
delay
,那么Future
就被用来获取它的值。如果我们调用上面的函数
我们将得到以下错误:
但是如果我们在函数调用之前使用await,它将在延迟之后给出函数的实际返回值
使用
await
for the Future获取返回值需要关键字async