nvo*_*igt 17 future async-await dart flutter flutter-futurebuilder
我收到以下错误:
A value of type 'Future<int>' can't be assigned to a variable of type 'int'
Run Code Online (Sandbox Code Playgroud)
它可能是另一种类型而不是int
,但基本上模式是
A value of type 'Future<T>' can't be assigned to a variable of type 'T'
Run Code Online (Sandbox Code Playgroud)
所以...
Future
?Future<T>
?nvo*_*igt 19
如果您熟悉Task<T>
orPromise<T>
和async
/await
模式,那么您可以直接跳到“如何在 Flutter 中使用带有小部件的 Future”部分。
好吧,文档说:
表示延迟计算的对象。
那是正确的。它也有点抽象和干燥。通常,函数会返回结果。依次。该函数被调用、运行并返回它的结果。在此之前,呼叫者等待。某些功能,特别是当它们访问硬件或网络等资源时,需要一点时间来完成。想象一下从 Web 服务器加载的头像图片、从数据库加载的用户数据或从设备内存加载的多种语言的应用程序文本。那可能会很慢。
默认情况下,大多数应用程序具有单一的控制流。当此流被阻塞时,例如等待需要时间的计算或资源访问,应用程序就会冻结。如果您足够大,您可能会记住这是标准,但在当今世界,这将被视为错误。即使有些事情需要时间,我们也会得到一些动画。一个微调器,一个沙漏,也许是一个进度条。但是,应用程序如何运行并显示动画,但仍然等待结果?答案是:异步操作。在您的代码等待某事时仍在运行的操作。现在编译器如何知道它是否应该真正停止一切并等待结果,还是继续所有后台工作并仅在此实例中等待?好吧,它无法自己解决这个问题。我们必须告诉 它。
这是通过称为async和await的模式实现的。它不是特定于flutter或dart 的,它在许多其他语言中以相同的名称存在。您可以在此处找到 Dart 的文档。
由于需要一些时间的方法不能立即返回,因此它会在完成后返回传递值的承诺。
那就是所谓的Future
。因此,从数据库加载数字的承诺会返回一段Future<int>
时间,而从互联网搜索中返回电影列表的承诺可能会返回Future<List<Movie>>
. AFuture<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;
Run Code Online (Sandbox Code Playgroud)
但是等等,我们是不是又回到了原点?不是又要等结果了吗?是的,我们确实如此。如果程序没有一些类似顺序流的东西,它们将是完全混乱的。但关键是使用await
我们告诉编译器的关键字,在这一点上,虽然我们想等待结果,但我们不希望我们的应用程序只是冻结。我们希望所有其他正在运行的操作(例如动画)继续进行。
但是,您只能await
在本身标记为async
并返回 a 的函数中使用关键字Future<T>
。因为当你await
做某事时,等待的函数不能再立即返回他们的结果。你只能归还你所拥有的,如果你必须等待它,你必须返回一个稍后交付的承诺。
Future<Pizza> getPizza() async {
Future<PizzaBox> delivery = orderPizza();
var pizzaBox = await delivery;
var pizza = pizzaBox.unwrap();
return pizza;
}
Run Code Online (Sandbox Code Playgroud)
我们的 getPizza 函数必须等待比萨饼,所以它不是Pizza
立即返回,而是返回一个比萨饼将在未来出现的承诺。现在,您又可以在await
某处使用 getPizza 函数了。
flutter 中的所有小部件都期望真正的价值。不是一些稍后会出现的价值的承诺。当按钮需要文本时,它不能使用文本稍后出现的承诺。它需要显示的按钮现在,所以它需要的文本现在。
但有时,您所拥有的只是一个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();
}
})
]);
}
}
Run Code Online (Sandbox Code Playgroud)
这就是你使用 FutureBuilder 来显示你的未来结果后的方式。
Max*_*lin 13
Future
以下是其他语言中与 Dart 的类比列表:
Promise
Future
Future
Task
就像其他语言一样,Future 是一种特殊类型的对象,它允许使用 async/await 语法糖,以同步/线性方式编写异步代码。您从异步方法返回 Future,而不是接受回调作为参数,并避免回调地狱 - Future 和回调都解决相同的问题(稍后触发一些代码),但以不同的方式。
jit*_*555 10
Future<T>
async
返回通过工作实现的潜在价值
例如:
Future<int> getValue() async {
return Future.value(5);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码返回的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'
Run Code Online (Sandbox Code Playgroud)
int
为了解决上面的问题, getValue() 应该在类型下接收
int value = await getValue(); // right way as it returning the potential value.
Run Code Online (Sandbox Code Playgroud)
我希望这个关键点能够提供有用的信息,我用两种不同的异步方法来展示它:
请注意以下方法,其中showLoading()
、getAllCarsFromApi()
和hideLoading()
是内部Async
方法。
如果我将await
关键字放在前面showLoading()
,操作会等到完成然后转到下一行,但我故意删除了,await
因为我需要在处理时同时显示加载对话框,所以这意味着方法是在不同的线程上处理的。最后隐藏加载对话框。getAllCarsFromApi()
showLoading()
getAllCarsFromApi()
hideLoading()
Future<List<Car>> getData() async{
showLoading();
final List<Car> cars = await getAllCarsFromApi();
hideLoading();
return cars;
}
Run Code Online (Sandbox Code Playgroud)
现在看另一个Async
方法,这里的getCarByIdFromApi()
方法需要一个id
从 计算出来的getCarIdFromDatabase()
,所以第一个方法之前必须有一个await
关键字,让Operation等待id
计算出来并传递给第二个方法。所以这里两个方法是在一个线程中依次处理的。
Future<Car> getCar() async{
int id = await getCarIdFromDatabase();
final Car car = await getCarByIdFromApi(id);
return car;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6736 次 |
最近记录: |