0
点赞
收藏
分享

微信扫一扫

Flutter学习11 - Future 与 FutureBuilder

星巢文化 04-08 22:01 阅读 1

1、Future

  • 可以利用 Future 实现异步调用

1.1、Future 的两种形式

自定义一个结果类

class Response {
  String _data;

  Response(this._data);
}

自定义方法实现 Future

Future<Response> testFuture() {
  var random = Random();
  int randomNumber = random.nextInt(10);
  if (randomNumber % 2 == 0) {
    return Future.value(Response('success: 偶数 $randomNumber'));
  } else {
    return Future.error('error: 奇数 $randomNumber');
  }
}
(1) then - onError
void main() {
  testFuture().then((value) {
    print(value._data);
  }, onError: (e) {
    print('1、onError: $e');
  });
}
(2) then - catchError
void main() {
  testFuture().then((value) {
    print(value._data);
  }).catchError((e) {
    print('2、catchError: $e');
  });
(3) 注意:当 onError 与 catchError 同时存在,只会调用 onError
void main() {
  //注:当 onError 与 catchError 同时存在,只会执行 onError
  testFuture().then((value) {
    print(value._data);
  }, onError: (e) {
    print('3、onError: $e');
  }).catchError((e) {
    print('3、catchError: $e');
  });
}

1.2、Future.whenComplete

then - catchError - whenComplete 类似于 try - catch - finally

Future<String> testFutureWhenComplete() {
  var random = Random();
  int randomNumber = random.nextInt(10);
  if (randomNumber % 2 == 0) {
    return Future.value('success: 偶数 $randomNumber');
  } else {
    return Future.error('error: 奇数 $randomNumber');
  }
}
void main(){
  testFutureWhenComplete()
      .then(print)
      .catchError(print)
      .whenComplete(() {
    print('完成!!!');
  });
}

1.3、Future.timeout

Future<String> testFutureTimeout() {
  return Future.delayed(const Duration(seconds: 2), () {
    var random = Random();
    int randomNumber = random.nextInt(10);
    if (randomNumber % 2 == 0) {
      return Future.value('success: 偶数 $randomNumber');
    } else {
      return Future.error('error: 奇数 $randomNumber');
    }
  });
}
void main(){
  //TimeoutException after 0:00:01.000000: Future not completed
  // Done!!!
  testFutureTimeout()
      .timeout(const Duration(seconds: 1))
      .then(print)
      .catchError(print)
      .whenComplete(() {
    print('Done!!!');
  });
}

2、FutureBuilder

  • FutureBuilder 是一个将异步操作和异步UI结合在一起的控件

在这里插入图片描述

2.1、构造函数

FutureBuilder({Key key, Future<T> future, T initialData,  AsyncWidgetBuilder<T> builder })
initialDataFuture完成前的初始化数据
future异步操作,返回Future对象
builder异步UI
builder
  • builder函数接受两个参数BuildContext context 与 AsyncSnapshot snapshot,返回一个widget
final AsyncWidgetBuilder<T> builder;
typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
AsyncSnapshot 包含信息
  • connectionState:表示与异步计算的连接状态,ConnectionState有四个值:none,waiting,active,done
none当前未连接到异步计算
waiting连接到异步计算等待交互
active异步计算进行中
done异步计算完成
  • data:异步计算接收到的最新数据
  • error:异步计算接收到的最新错误数据
  • hasData:检查是否包含非空数据
  • hasError:检查是否包含错误值

2.2、代码示例

在这里插入图片描述

FutureBuilderDemo.dart

import 'dart:convert';

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

class FutureBuilderDemo extends StatefulWidget {
  const FutureBuilderDemo({super.key});

  
  State<FutureBuilderDemo> createState() => _FutureBuilderDemoState();
}

class _FutureBuilderDemoState extends State<FutureBuilderDemo> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('FutureBuilder Demo'),
      ),
      body: FutureBuilder<PhoneEntity>(
        future: _doGet(),
        builder: (BuildContext context, AsyncSnapshot<PhoneEntity> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
              return const Text('状态:无');
            case ConnectionState.waiting:
              //进度条
              return const Center(
                child: CircularProgressIndicator(),
              );
            case ConnectionState.active:
              return const Text('状态:激活');
            case ConnectionState.done:
              if (snapshot.hasError) {
                //失败
                return Text(
                  '${snapshot.error}',
                  style: const TextStyle(color: Colors.red),
                );
              } else {
                return Column(
                  children: [
                    Text('code: ${snapshot.data!.code}'),
                    Text('city: ${snapshot.data!.data!.city}'),
                    Text('province: ${snapshot.data!.data!.province}'),
                    Text('sp: ${snapshot.data!.data!.sp}'),
                  ],
                );
              }
          }
        },
      ),
    );
  }

  Future<PhoneEntity> _doGet() async {
    var url =
        Uri.parse('https://cx.shouji.360.cn/phonearea.php?number=17688888888');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      //请求成功
      try {
        var json = response.body;
        var map = jsonDecode(json);
        var entity = PhoneEntity.fromJson(map);
        return Future.value(entity);
      } catch (e) {
        return Future.error('数据异常: ${e.toString()}');
      }
    } else {
      //请求失败
      return Future.error('请求失败 ! ! !');
    }
  }
}

/**********************/

///
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
///
class PhoneEntityData {
/*
{
  "province": "广东",
  "city": "广州",
  "sp": "联通"
}
*/

  String? province;
  String? city;
  String? sp;

  PhoneEntityData({
    this.province,
    this.city,
    this.sp,
  });

  PhoneEntityData.fromJson(Map<String, dynamic> json) {
    province = json['province']?.toString();
    city = json['city']?.toString();
    sp = json['sp']?.toString();
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['province'] = province;
    data['city'] = city;
    data['sp'] = sp;
    return data;
  }
}

class PhoneEntity {
/*
{
  "code": 0,
  "data": {
    "province": "广东",
    "city": "广州",
    "sp": "联通"
  }
}
*/

  int? code;
  PhoneEntityData? data;

  PhoneEntity({
    this.code,
    this.data,
  });

  PhoneEntity.fromJson(Map<String, dynamic> json) {
    code = json['code']?.toInt();
    data =
        (json['data'] != null) ? PhoneEntityData.fromJson(json['data']) : null;
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['code'] = code;
    if (data != null) {
      data['data'] = this.data!.toJson();
    }
    return data;
  }
}

main.dart

import 'package:flutter/material.dart';

import 'FutureBuilderDemo.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Leon Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const FutureBuilderDemo(),
    );
  }
}
举报

相关推荐

0 条评论