Flutter异步:Future与FutureBuilder实用技巧

什么是Future

表示在接下来的某个时间的值或错误,借助Future我们可以再Flutter实现异步操作。

它类似于ES6中的Promise,提供then和catchError的链式调用

Future是dart:async包中的一个类,使用它的时候需要导入dart:async包,Future有两种状态:

  • pending : 执行中
  • completed : - 执行结束,分两种情况要么成功要么失败

Future的常见用法

使用future.then获取future的值与捕获future的异常

Future testFuture() {
  //throw new Error();
  return Future.value("success");
  //return Future.error("error");
}

void main() {
  testFuture().then((s) {
	print(s);
	}, onError: (e) {
    print("onError:");
    print(e);
  }).catchError((e) {
    print("catchError:");
    print(e);
  });
}

如果catchError与onError同时存在,则只会调用onError

结合async await

Future是异步的,如果我们要将异步转同步,那么可以借助async await 来完成

import 'dart:async';

test() async {
  int result = await Future.delayed(Duration(milliseconds: 2000),(){
    return Future.value(123);
  });
  print("t3:"+DateTime.now().toString());
  print(result);
}

void main() {
  print("t1:"+DateTime.now().toString());
  test();
  print("t2:"+DateTime.now().toString());
}

运行结果

I/flutter (20667): t1:2019-06-14 15:58:04.892591
I/flutter (20667): t2:2019-06-14 15:58:04.941420
I/flutter (20667): t3:2019-06-14 15:58:06.951207

future.whenComplete

有时候我们需要在Future结束的时候做些事情,我们知道then().catchError()的模式类似于try-catch,try-catch有个finally代码块,而future.whenComplete就是Future的finally。

Future.value("success")
.then((s) {
    print(s);
  }).catchError((e) {
    print("catchError:");
    print(e);
  }).whenComplete((){
    print("complete")
  });

future.timeout

完成一个异步操作可能需要很长的时间,比如网络请求,但有时我们需要为异步操作设置一个超时时间。

new Future.delayed(new Duration(seconds: 3), () {})
  .timeout(new Duration(seconds: 2))
  .then((s) {
print("then");
  }).catchError(() {
    print("catchError");
  });

运行后可以看到日志

E/flutter (20667): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: TimeoutException after 0:00:02.000000: Future not completed

什么是FutureBuilder

FutureBuilder是一个将异步操作和异步UI更新结合在一起的类,通过它我们可以将网络请求,数据库读取等结果更新到页面上。

FutureBuilder常见的用法

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  State createState() => _MyAppState();
}

class _MyAppState extends State {
  String showResult = '';
  Future fetchPost() async {
    final response = await http.get('http://www.devio.org/io/flutter_app/json/test_common_model.json');
    Utf8Decoder utf8decoder = Utf8Decoder(); //fix 中文乱码
    var result = json.decode(utf8decoder.convert(response.bodyBytes));
    return CommonModel.fromJson(result);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Future与FutureBuilder实用技巧'),
        ),

        body: FutureBuilder(
            future: fetchPost(),
            builder:
                (BuildContext context, AsyncSnapshot snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  return new Text('Input a URL to start');
                case ConnectionState.waiting:
                  return new Center(child: new CircularProgressIndicator());
                case ConnectionState.active:
                  return new Text('');
                case ConnectionState.done:
                  if (snapshot.hasError) {
                    return new Text(
                      '${snapshot.error}',
                      style: TextStyle(color: Colors.red),
                    );
                  } else {
                    return new Column(children: [
                      Text('icon:${snapshot.data.icon}'),
                      Text('statusBarColor:${snapshot.data.statusBarColor}'),
                      Text('title:${snapshot.data.title}'),
                      Text('url:${snapshot.data.url}')
                    ]);
                  }
              }
            }),
      ),
    );
  }
}

class CommonModel {
  final String icon;
  final String title;
  final String url;
  final String statusBarColor;
  final bool hideAppBar;
  CommonModel(
      {this.icon, this.title, this.url, this.statusBarColor, this.hideAppBar});
  factory CommonModel.fromJson(Map json) {
    return CommonModel(
      icon: json['icon'],
      title: json['title'],
      url: json['url'],
      statusBarColor: json['statusBarColor'],
      hideAppBar: json['hideAppBar'],
    );
  }
}

其他

详见https://www.jianshu.com/p/78fe79648596

你可能感兴趣的:(跨平台移动开发)