在Android开发中,异步编程是必不可少的,好比网络请求、IO操做等不少都是异步操做,而在Android原生中,有主线程和工做线程的概念,耗时操做都是要放到工做线程中的,ui要在主线程中更新,所以,原生Android开发中对线程的处理是必不可少的,幸运的是,一些第三方库例如Rxjava、RxAndroid让咱们的线程切换起来十分的方便。html
可是Flutter是基于Datt语言实现的,而Dart中的代码是在一个线程中运行的,所以,Flutter也是单线程模型的。
参考资料能够看官方说明:Dart异步编程
这里不由有一个问题,Flutter为啥要用Dart呢?单线程会不会比多线程的效率低呢?
java
先无论效率的问题了,实际运行起来速度仍是很快的。git
也就是说,咱们在Flutter中对异步的处理并非像原生Android那样是多个线程去处理的。
那么,Flutter中是怎么处理异步操做的呢?github
Flutter给咱们提供了Future对象以及async和await关键字来支持异步编程。
咱们首先来看看 Futureweb
Future是一个抽象类,咱们经常使用的方法以下
编程
Future对象表示异步操做的结果,咱们一般经过then()来处理返回的结果
async用于标明函数是一个异步函数,其返回值类型是Future类型
await用来等待耗时操做的返回结果,这个操做会阻塞到后面的代码api
网络请求是很是典型的异步任务,下面咱们就来结合网络请求来看看Flutter中的异步是如何使用的。网络
网络请求的方式有不少,这里我就直接用目前比较好用的DIO网络请求库 了,你也可使用官方文档中的网络请求 ,都是能够的。多线程
下面咱们来简单用一用网络请求。app
这里我使用的聚合上的一个接口
接口地址:http://v.juhe.cn/toutiao/index?type=keji&key=4c52313fc9247e5b4176aed5ddd56ad7
关于DIO如何使用这里就不讲了,Github上文档很详细,使用起来也很简单。
下面咱们直接用:
首先要先导包
import 'package:dio/dio.dart';
请求接口获取数据的方法
/** * 请求接口获取数据 */ Future<Response> getData() async { String url = "http://v.juhe.cn/toutiao/index"; String key = "4c52313fc9247e5b4176aed5ddd56ad7"; String type = "keji"; print("开始请求数据"); Response response = await Dio().get(url, queryParameters: {"type": type, "key": key}); print("请求完成"); return response; }
注意一下几点:
而后咱们就能够在main函数中来接收网络请求后的结果了:
main() { getData().then((result) { print("接口返回的数据是:${result}"); }).whenComplete((){ print("异步任务处理完成"); }).catchError((){ print("出现异常了"); }); print("我是在请求数据后面的代码呦!"); }
咱们来看看执行的结果:
这样一来,咱们就完成了Flutter中的异步操做了,能够看到,相对于原生Android来说,Flutter中的异步是很是简单的。
FutureBuilder 实际上就是对Future进行封装的一个Widget。咱们先来看看他的构造方法
const FutureBuilder({ Key key, this.future, this.initialData, @required this.builder })
其中,
future接收Future<T>
类型的值,实际上就是咱们的异步函数,一般状况下都是网络请求函数
initialData 表示在异步函数执行完成以前能够给快照进行使用,简单理解就是初始数据,应该不是很经常使用
builder:接收一个AsyncWidgetBuilder<T>
类型的值,看源码
/// Signature for strategies that build widgets based on asynchronous /// interaction. /// /// See also: /// /// * [StreamBuilder], which delegates to an [AsyncWidgetBuilder] to build /// itself based on a snapshot from interacting with a [Stream]. /// * [FutureBuilder], which delegates to an [AsyncWidgetBuilder] to build /// itself based on a snapshot from interacting with a [Future]. typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
AsyncWidgetBuilder为构建器提供了一个AsyncSnapshot对象,咱们再来看看AsyncSnapshot的源码
下图是AsyncSnapshot中的属性和方法
AsyncSnapshot中封装了connectionState(链接状态)、data(实际上就是future执行后返回的数据)以及error(实际上就是future错误时返回的错误信息)
data和error比较好理解,咱们主要来看看connectionState
connectionState是一个enum 类型的值,其源码以下
enum ConnectionState { /// Not currently connected to any asynchronous computation. /// /// For example, a [FutureBuilder] whose [FutureBuilder.future] is null. none, /// Connected to an asynchronous computation and awaiting interaction. waiting, /// Connected to an active asynchronous computation. /// /// For example, a [Stream] that has returned at least one value, but is not /// yet done. active, /// Connected to a terminated asynchronous computation. done, }
搞清楚这些,咱们就能够开心的使用FutureBuilder了。
一个很常见的需求,在首次进入页面时,此时数据还须要从网络上获取,咱们但愿在网络请求完成以前显示一个加载页面,请求完成以后再显示数据。此时,咱们就可使用FutureBuilder来完成了
首先是接口请求函数,为了更明显的能看到加载控件的显示,这里的异步请求函数中我延时3秒后再请求数据,代码以下
import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_async/widget/loading.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: '新闻列表', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: '新闻列表'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: FutureBuilder( future: _getNews(), builder: (BuildContext context, AsyncSnapshot<Response> snapshot) { /*表示数据成功返回*/ if (snapshot.hasData) { Response response = snapshot.data; return Text("${response.data.toString()}"); } else { return LoadingWidget(); } }, )); } } /** * 请求接口获取数据 */ Future<Response> _getNews() async { await Future.delayed(Duration(seconds: 3), () { print("延时三秒后请求数据"); }); String url = "http://v.juhe.cn/toutiao/index"; String key = "4c52313fc9247e5b4176aed5ddd56ad7"; String type = "keji"; print("开始请求数据"); Response response = await Dio().get(url, queryParameters: {"type": type, "key": key}); print("请求完成"); return response; }
运行效果:
下面是demo,须要的能够下载:
flutter_async Demo
若是你以为本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个承认。也能够关注个人 Flutter 博客专栏,我会不按期的更新,若是文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!