博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dart flutter_在Dart和Flutter中使用期货和流
阅读量:2504 次
发布时间:2019-05-11

本文共 8588 字,大约阅读时间需要 28 分钟。

dart flutter

The most important features of almost any app relies on the ability to interact with external API’s and databases. With that comes the problem of dealing with code that runs in an order different to how it was written while waiting for certain requests and operations to complete. We’re going to look into how Dart, particularly for Flutter, works with managing that complexity.

几乎所有应用程序的最重要功能都依赖于与外部API和数据库进行交互的能力。 随之而来的问题是,处理代码的顺序与等待某些请求和操作完成时的编写顺序不同。 我们将研究Dart(尤其是Flutter)如何管理这种复杂性。

Much of this may seem very familiar if you come from a front-end background, since Dart resembles JavaScript in a lot of ways. I’m going to assume that you have little to no knowledge of asynchronous concepts and techniques.

如果您来自前端背景,那么其中的许多内容可能看起来非常熟悉,因为Dart在很多方面都类似于JavaScript。 我将假设您几乎不了解异步概念和技术。

建立 (Setup)

For our first example, I’m going to be using the , which will just return some basic information on whatever country we give it. This will also of course require the .

对于我们的第一个示例,我将使用 ,它将仅返回我们提供的任何国家的一些基本信息。 当然,这也需要 。

For our UI we’ll just use a centered button that will run our GetCountry function.

对于我们的UI,我们将只使用一个将运行GetCountry函数的居中按钮。

pubspec.yaml
pubspec.yaml
dependencies:  flutter:    sdk: flutter  http: ^0.12.0+2
main.dart
main.dart
import 'package:flutter/material.dart';import 'package:http/http.dart' as http;import 'dart:convert'; //This allows us to convert the returned JSON data into something Dart can use.void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      home: MyHomePage(),    );  }}class MyHomePage extends StatelessWidget {  void GetCountry() async {}  @override  Widget build(BuildContext context) {    return Scaffold(      body: Center(        child: MaterialButton(          onPressed: () => GetCountry(),          child: Container(            color: Colors.blue,            padding: EdgeInsets.all(15),            child: Text('Get Country', style: TextStyle(color: Colors.white))),        ),      ),    );  }}

同步代码的问题 (The Problem with Synchronous Code)

While having every line in our code run in order is pretty straight forward to understand, that’s not always possible to achieve. When we send a request for information to an API, it’ll take some time before we get a response while our machine will be waiting for it to complete, halting things that may have nothing to do with the initial request. The problem is we don’t want our script to stop running every time something takes a while, but we also wouldn’t want it to run anything that relies on the return data prematurely, which could cause an error despite the request being successful.

尽管让我们的代码中的每一行按顺序运行很容易理解,但这并非总是可以实现的。 当我们向API发送信息请求时,我们将花一些时间才能得到响应,而我们的机器将等待响应完成,从而停止可能与初始请求无关的事情。 问题是我们不希望脚本每次花点时间都停止运行,但是我们也不希望脚本过早地运行依赖于返回数据的任何东西,尽管请求成功,但是这可能会导致错误。

The best of both worlds would be to set up our logic in a way that allows our machine to work ahead while waiting for a request to return while only letting code dependent on that request run when it’s available.

最好的办法是设置逻辑,使我们的机器在等待请求返回的同时继续工作,同时仅在依赖请求时才运行依赖于该请求的代码。

Our app’s data is most likely going to be in one of four forms, depending on whether or not they’re already available and whether or not they’re singular.

我们的应用程序数据很可能采用以下四种格式之一,具体取决于它们是否已经可用以及它们是否为单个。

You’re probably already very familiar with the standard strings and lists, futures and streams are the more interesting things that we’ll be exploring.

您可能已经非常熟悉标准字符串和列表,期货和数据流是我们将要探索的更有趣的事物。

然后/ CatchError (Then/CatchError)

Very similar to , Dart lets us chain methods together so we can easily pass the return data from one to the next and it even returns a promise-like data type, called futures. Futures are any singular type of data, like a string, which will be available later.

与非常相似,Dart使我们可以将方法链接在一起,这样我们就可以轻松地将返回数据从一个传递到另一个,甚至可以返回类似promise的数据类型,称为Future。 期货是任何奇异类型的数据,例如字符串,将在以后提供。

To use this technique, we just need to do whatever operations we need, like send a get request to REST Countries, then just chain .then with our returned data passed-in as a parameter, use it however we want and/or we could keep chaining .then forever. For error handling we can cap off our chain with a .catchError and throw whatever was passed to it.

要使用此技术,我们只需要执行所需的任何操作,例如向REST国家/地区发送get请求,然后仅进行链接。然后将返回的数据作为参数传入,就可以.then使用它,并且/或者我们可以保持链接.then永远。 对于错误处理,我们可以使用.catchError我们的链,并抛出传递给它的所有内容。

main.dart
main.dart
// Since we're returning a Future, we must set our function to type Future.Future GetCountry(country) {    String countryUrl = 'https://restcountries.eu/rest/v2/name/$country';    http      .get(countryUrl)      .then((response) => jsonDecode(response.body)[0]['name'])      .then((decoded) => print(decoded))      .catchError((error) => throw(error));  }// Update our Button to use our functionMaterialButton(  onPressed: () => GetCountry('canada'),  (...))

异步/等待 (Async/Await)

Try/CatchError definitely works well, but there’s also an alternative syntax that many find to be much for readable.

Try / CatchError确实可以很好地工作,但是还有一种替代语法,很多人认为它可读性强。

Async/Await works exactly the same , we use the async keyword after our function name and add the await keyword before anything that needs some time to run, like our get request. Now everything after it will be ran when a value has been returned. For error handling we can just throw the whole thing into a try/catch block.

Async / Await的工作原理与完全相同,我们在函数名称后使用async关键字,并在需要一些时间才能运行的内容(例如我们的get请求)之前添加await关键字。 现在,返回值后,它将执行所有后续操作。 对于错误处理,我们可以将整个内容放入try / catch块中。

main.dart
main.dart
Future GetCountry(country) async {  String countryUrl = 'https://restcountries.eu/rest/v2/name/$country';  try {    http.Response response = await http.get(countryUrl);    Object decoded = jsonDecode(response.body)[0]['name'];    print(decoded);  } catch (e) { throw(e); }}

(Streams)

Something special with Dart is its use of streams for when we have many values being loaded asynchronously and instead of opening a connection once, like with our get request, we can make it stay open and ready for new data.

Dart的特殊之处在于,当我们有许多值被异步加载时,它可以使用流,而不是像get请求那样一次打开连接,我们可以使其保持打开状态并为新数据做好准备。

Since our example would get a bit too complicated by setting it up with a backend that allows streams, like or GraphQL, we’ll simulate a change in a chat application database by emitting a new ‘message’ every second.

由于我们的示例通过允许流的后端进行设置(例如或GraphQL)而变得有点复杂,因此我们将通过每秒发出一个新的“消息”来模拟聊天应用程序数据库中的更改。

We can create a simple stream with the StreamController class, which works similarly to a List, since it’s just a list of futures. We can control our stream with the properties on stream, like listen and close to start and stop it.

我们可以使用StreamController类创建一个简单的流,该类的工作方式类似于List ,因为它只是一个期货列表。 我们可以使用stream的属性来控制stream ,例如listenclose来启动和停止它。

It’s important to always use close() when your widget is removed. Streams will run continuously until they are shut off and will eat away at computing power even when the original widget is gone.

删除小部件时始终使用close()很重要。 流将一直运行,直到它们被关闭为止,并且即使原始窗口小部件消失了也会吞噬计算能力。

main.dart
main.dart
StreamController
streamController = StreamController(); void newMessage(int number, String message) { final duration = Duration(seconds: number); Timer.periodic(duration, (Timer t) => streamController.add(message)); } void initState() { super.initState(); streamController.stream.listen((messages) => print(messages)); newMessage(1, 'You got a message!'); } void dispose() { streamController.close(); super.dispose(); }

Standard streams can be a bit limited in that they only allow for one listener at a time. Instead we can use the broadcast property on the StreamController class to open up multiple channels.

标准流可能会有所限制,因为它们一次只允许一个侦听器。 相反,我们可以使用StreamController类上的broadcast属性来打开多个频道。

main.dart
main.dart
StreamController
streamController = StreamController.broadcast();void initState() { super.initState(); streamController.stream.listen((messages) => print('$messages First')); streamController.stream.listen((messages) => print('$messages Second')); newMessage(1, 'You got a message!');}

结论 (Conclusion)

For me, working with asynchronous code was one of the hardest parts about learning programming and I hope I helped spare someone from any of the difficulty of understanding this strange style of code. Hopefully this short intro to asynchronous programming in Dart was helpful in your start to developing intelligent and dynamic apps.

对我来说,使用异步代码是学习编程最困难的部分之一,我希望我可以帮助人们摆脱理解这种奇怪代码风格的任何困难。 希望Dart异步编程的简短介绍对您开始开发智能和动态应用程序有所帮​​助。

翻译自:

dart flutter

转载地址:http://nphgb.baihongyu.com/

你可能感兴趣的文章
程序在本地能启动而预发布不能启动
查看>>
Lucene、ES好文章
查看>>
有关定时器setTimeout()、setInterval()详解
查看>>
刷题总结——次小生成树(bzoj1977 最小生成树+倍增)
查看>>
html5-2 html实体和颜色有哪些
查看>>
饺紫猫配色教程
查看>>
第三百六十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)用Django实现搜索功能...
查看>>
第八十节,CSS3边框图片效果
查看>>
第一百九十五节,jQuery EasyUI,Resizable(调整大小)组件
查看>>
Gym 101128F Landscaping(网络流)题解
查看>>
使用Expression进行查询拼接
查看>>
父页面获得子页面的值
查看>>
elment 中 el-table 进行校验
查看>>
SQL server 动态查询(表名或字段动态),并且获取想得到的返回值结果
查看>>
Nginx配置详解
查看>>
突袭HTML5之WebGL 3D概述(上) - WebGL原生开发
查看>>
SQL 映射的 XML 文件
查看>>
转:如何成为Linux高手
查看>>
Oracle数据库修改LISTENER的监听端口
查看>>
jvm 监控工具
查看>>