当前位置: 首页 > news >正文

Flutter中的异步编程

目录

前言

1. Future 和 async/await

1.Future

1.什么是Future?

2.Flutter的三种状态

1.未完成(Uncompleted) 

1.定义      

2.处理未完成的Future

2.已完成(Completed with a value)

1.概念

2.处理已完成的Future

3.使用async/await

4.Future的已完成状态的处理

3.已失败(Completed with an error)

1.概念

2.处理失败状态的Future

3.使用 async/await

4.捕获和处理错误的最佳实践

1.始终捕获错误

2.提供用户反馈

3.记录错误

3.创建Future

1.使用Future构造函数

2.使用Future.delayed

3.使用Future.value和Future.error

4.处理Future

1.使用then和catchError

2.使用async/await

3.Future的链式调用

2. Stream

1.Stream的两种类型

2.创建Stream

1.使用StreamController

2.使用异步生成器函数

3.监听Stream

4.使用StreamBuilder

5.Stream的高级用法

1.转换Stream

2.合并Stream

6.总结

3.FutureBuilder和StreamBuilder

1.FutureBuilder

2.StreamBuilder


前言

        在Flutter应用程序开发中,异步编程是必不可少的。异步编程使应用程序能够在不阻塞主线程的情况下执行耗时操作,如网络请求、文件读取和数据库访问。本文将介绍Flutter中常用的异步编程方法及其最佳实践。

1. Future 和 async/await

1.Future

1.什么是Future?

        在Flutter中,Future是一个用于表示异步操作结果的类。它代表一个在将来某个时刻会完成的计算,类似于其他编程语言中的Promise。Future非常适合处理那些需要一些时间才能完成的操作,例如网络请求、文件读取或其他耗时任务。

2.Flutter的三种状态

1.未完成(Uncompleted) 
1.定义      

        表示异步操作尚未完成。在未完成状态的时候,Future尚未提供结果,也没有抛出错误。

        当你调用一个异步函数时,它会返回一个未完成的 Future。该 Future 正在等待函数的异步操作完成或抛出错误。

        以下是一个创建和使用Future的示例,展示Future在未完成状态时的行为:

Future<String> fetchData() {// 创建一个延迟两秒后完成的Futurereturn Future.delayed(Duration(seconds: 2), () => 'Data fetched');
}void main() {print('Fetching data...');fetchData().then((result) {print(result);}).catchError((error) {print('Error: $error');});print('Waiting for data...');
}

        控制台输入信息如下:

Fetching data...
Waiting for data...
Data fetched

        这里可以看到,在调用fetchData之后和Future完成之前,控制台输出了”Waiting for data…”。这表示在这段时间内,Future处于未完成状态。

2.处理未完成的Future

        通常,我们使用then方法来处理Future完成时的结果,使用catchError方法来处理Future失败时的错误。

        此外,可以使用await关键字在异步函数中等待Future完成:

Future<void> fetchDataAndPrint() async {print('Fetching data...');try {String result = await fetchData();print(result);} catch (error) {print('Error: $error');}print('Data fetching completed.');
}void main() {fetchDataAndPrint();
}

        执行这个代码时,控制台的输出如下:

Fetching data...
Data fetched
Data fetching completed.

2.已完成(Completed with a value)
1.概念

        已完成状态表示异步操作成功完成,并返回了结果。

2.处理已完成的Future

        当Future进入已完成状态时,我们可以使用then方法来处理成功的结果,使用catchError方法来处理失败的错误。另外,可以使用async/await来简化异步代码。

        以下是一个创建和使用Future的示例,展示如何处理已完成状态的Future:

Future<String> fetchData() {
  // 创建一个延迟两秒后完成的Future
  return Future.delayed(Duration(seconds: 2), () => 'Data fetched');
}

void main() {
  print('Fetching data...');
  
  fetchData().then((result) {
    // 当Future完成时,处理结果
    print(result);
  }).catchError((error) {
    // 当Future失败时,处理错误
    print('Error: $error');
  });

  print('Waiting for data...');
}

        执行这段代码时,控制台的输出如下:

Fetching data...
Waiting for data...
Data fetched

        在上面的实例中:

1.fetchData函数返回一个在两秒后完成的Future,并返回字符串"Data fetched"。

2.使用then方法处理Future完成时的结果,输出"Data fetched"。

3.使用catchError方法处理Future失败时的错误(示例中未发生错误)。

3.使用async/await

        async/await语法使得处理异步操作更加直观和简洁。以下是同样功能的代码,使用async/await:

Future<void> fetchDataAndPrint() async {
  print('Fetching data...');
  
  try {
    // 使用await等待Future完成
    String result = await fetchData();
    print(result);
  } catch (error) {
    print('Error: $error');
  }

  print('Data fetching completed.');
}

void main() {
  fetchDataAndPrint();
}    

        执行这个代码时,控制台的输出如下:

Fetching data...
Data fetched
Data fetching completed.

        在这个示例中:

1.使用await关键字等待Future完成,并获取其结果。

2.try块用于捕获可能的错误,并在catch块中处理错误。

4.Future的已完成状态的处理

        在Flutter的完成状态中,有失败和成功两种情况。

1.对于成功完成的Future,使用then方法处理完成的Future,或者在async函数中是用await。

2.对于失败完成的Future,使用catchError方法处理失败完成的Future,或者在async函数中使用try/catch。

3.已失败(Completed with an error)
1.概念

        Future的失败状态表示该异步操作已经完成,但由于某种原因失败,并抛出了一个错误。

2.处理失败状态的Future

        当Future进入失败状态时,可以使用catchError方法来处理失败的错误,或者在async/await语法中使用try/catch块来捕获和处理错误。

        以下是一个创建和使用Future的示例,展示如何处理失败状态的Future:

Future<String> fetchData() {
  // 创建一个延迟两秒后失败的Future
  return Future.delayed(Duration(seconds: 2), () => throw 'Failed to fetch data');
}

void main() {
  print('Fetching data...');
  
  fetchData().then((result) {
    // 当Future成功完成时,处理结果
    print(result);
  }).catchError((error) {
    // 当Future失败时,处理错误
    print('Error: $error');
  });

  print('Waiting for data...');
}

        执行这段代码时,控制台的输出如下:

Fetching data...
Waiting for data...
Error: Failed to fetch data

        在上面这个示例中:

1. fetchData函数返回一个在两秒后失败的Future,并抛出字符串"Failed to fetch data"。

2. 使用then方法处理Future成功完成时的结果(在此示例中不会被调用)。

3. 使用catchError方法处理Future失败时的错误,输出"Error: Failed to fetch data"。

3.使用 async/await

        async/await语法使得处理异步操作的失败更加直观和简洁。以下是同样功能的代码,使用async/await:

Future<void> fetchDataAndPrint() async {
  print('Fetching data...');
  
  try {
    // 使用await等待Future完成
    String result = await fetchData();
    print(result);
  } catch (error) {
    // 捕获并处理错误
    print('Error: $error');
  }

  print('Data fetching completed.');
}

void main() {
  fetchDataAndPrint();
}

        执行这个代码时,控制台的输出如下:

Fetching data...
Error: Failed to fetch data
Data fetching completed.

        在这个示例中:

1. 使用await关键字等待Future完成,并获取其结果。

2. try块用于捕获可能的错误,并在catch块中处理错误。

4.捕获和处理错误的最佳实践

        理解和处理Future的失败状态是Flutter异步编程的重要部分。通过使用catchError和try/catch语法,可以有效地捕获和处理异步操作中的错误,从而编写更健壮和稳定的Flutter应用程序。

1.始终捕获错误

        无论使用then和catchError还是async/await,始终确保捕获并处理Future中的错误,以避免未处理的异常。

2.提供用户反馈

        在用户界面上提供适当的反馈,如显示错误消息或提示用户重试操作。

3.记录错误

        在开发和调试过程中,记录错误信息有助于查找和修复问题。

3.创建Future

        创建一个Future非常简单,可以使用Future构造函数、Future.delayed、Future.value和Future.error等方法。

1.使用Future构造函数
Future<String> fetchData() {return Future(() {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);});
}
2.使用Future.delayed
Future<String> fetchData() {return Future.delayed(Duration(seconds: 2), () {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);});
}
3.使用Future.value和Future.error
void main() {Future.value('Immediate data').then((data) {print(data);});Future.error('An error occurred').catchError((error) {print(error);});
}

4.处理Future

        处理Future通常有两种方式:使用then和catchError方法,或者使用async/await语法。

1.使用then和catchError
Future<String> fetchData() {return Future.delayed(Duration(seconds: 2), () {return 'Data fetched';});
}void main() {fetchData().then((data) {print(data);}).catchError((error) {print('Error: $error');});
}
2.使用async/await
Future<String> fetchData() async {await Future.delayed(Duration(seconds: 2));return 'Data fetched';
}void main() async {try {String data = await fetchData();print(data);} catch (error) {print('Error: $error');}
}
3.Future的链式调用

        多个Future可以通过链式调用连接在一起,从而依次处理多个异步操作。

Future<void> fetchData() {
  return Future.delayed(Duration(seconds: 2), () {
    print('Step 1: Data fetched');
  }).then((_) {
    return Future.delayed(Duration(seconds: 1), () {
      print('Step 2: Additional data fetched');
    });
  }).then((_) {
    print('Step 3: All steps completed');
  });
}

void main() {
  fetchData();
}

2. Stream

        在Flutter中,Stream用于表示一系列异步数据事件。与Future不同,Stream可以提供多个值而不是单个值。它非常适合处理诸如用户输入、实时数据更新和传感器数据等连续数据流。本文将详细介绍Flutter中`Stream`的基本概念和用法。

1.Stream的两种类型

        1.单订阅Stream(Single-subscription Stream):只能被单个监听器(listener)监听。这种Stream适用于大多数情况。
        2.广播Stream(Broadcast Stream):可以被多个监听器同时监听。这种Stream适用于需要多个订阅者的情况,如事件总线(Event Bus)。

2.创建Stream

        创建Stream有多种方式,常见的包括使用StreamController和异步生成器函数。

1.使用StreamController

        StreamController用于创建和管理Stream。

void main() {// 创建一个StreamControllerfinal controller = StreamController<int>();// 获取Streamfinal stream = controller.stream;// 监听Streamstream.listen((data) {print('Data: $data');}, onDone: () {print('Stream closed');});// 添加数据到Streamcontroller.add(1);controller.add(2);controller.add(3);// 关闭Streamcontroller.close();
}

        执行这个代码时,控制台的输出如下:

Data: 1
Data: 2
Data: 3
Stream closed

2.使用异步生成器函数

        可以使用async*和yield关键字创建Stream。

Stream<int> countStream(int to) async* {for (int i = 1; i <= to; i++) {await Future.delayed(Duration(seconds: 1));yield i;}
}void main() {final stream = countStream(5);stream.listen((data) {print('Data: $data');}, onDone: () {print('Stream closed');});
}

        执行这个代码时,控制台的输出如下:

Data: 1
Data: 2
Data: 3
Data: 4
Data: 5
Stream closed

3.监听Stream

        使用listen方法可以监听Stream,并处理接收到的数据和错误。

stream.listen((data) {print('Data: $data');},onError: (error) {print('Error: $error');},onDone: () {print('Stream closed');},cancelOnError: false, // 当为true时,接收到错误后将取消订阅
);

4.使用StreamBuilder

        在Flutter中,StreamBuilder小部件用于根据Stream构建UI。它会监听Stream并在每次接收到数据时重新构建UI。

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StreamBuilder Example'),
      ),
      body: Center(
        child: StreamBuilder<int>(
          stream: countStream(5),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else if (!snapshot.hasData) {
              return Text('No Data');
            } else {
              return Text('Count: ${snapshot.data}');
            }
          },
        ),
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: MyHomePage()));

        在这个示例中,StreamBuilder监听countStream,并根据Stream的状态更新UI。

5.Stream的高级用法

1.转换Stream

        使用Stream的转换方法可以方便地处理数据,例如使用map方法转换数据:

Stream<int> countStream(int to) async* {for (int i = 1; i <= to; i++) {await Future.delayed(Duration(seconds: 1));yield i;}
}void main() {final stream = countStream(5).map((data) => data * 2);stream.listen((data) {print('Transformed Data: $data');});
}

2.合并Stream

        可以使用StreamGroup来合并多个Stream:

void main() {final stream1 = Stream.fromIterable([1, 2, 3]);final stream2 = Stream.fromIterable([4, 5, 6]);final mergedStream = StreamGroup.merge([stream1, stream2]);mergedStream.listen((data) {print('Merged Data: $data');});
}

6.总结

        Stream在Flutter中是处理异步数据事件的强大工具。通过理解和使用StreamController、异步生成器函数以及StreamBuilder,可以有效地处理和显示连续的数据流。希望本文能帮助你更好地理解和使用Flutter中的Stream。

        Future 表示不会立即完成的计算。普通函数会返回结果,而异步函数则会返回 Future,后者最终会包含结果。Future 会告诉您结果何时准备就绪。

        Stream(流)是一系列异步事件。它类似于异步 Iterable — 流不会在您请求时获取下一个事件,而是在事件准备就绪时告诉您有事件发生。

3.FutureBuilder和StreamBuilder

        FutureBuilder和StreamBuilder是Flutter中用于处理异步数据的两个常用小部件。

1.FutureBuilder

        FutureBuilder用于构建依赖于Future的widget。

FutureBuilder<String>(future: fetchUserOrder(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator();} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else {return Text('Order: ${snapshot.data}');}},
);

2.StreamBuilder

        StreamBuilder用于构建依赖于Stream的widget。

StreamBuilder<int>(stream: countStream(5),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {return CircularProgressIndicator();} else if (snapshot.hasError) {return Text('Error: ${snapshot.error}');} else if (!snapshot.hasData) {return Text('No Data');} else {return Text('Count: ${snapshot.data}');}},
);
http://www.lryc.cn/news/421655.html

相关文章:

  • vue3 路由带传参跳转;刷新后消失。一次性参数使用。
  • Unity新输入系统结构概览
  • 18104 练习使用多case解题
  • 【AI人工智能】文心智能体 - 你的专属车牌设计师
  • Linux-服务器硬件及RAID配置实验
  • 白屏检测系统的设计与实现
  • Real-Time Open-Vocabulary Object Detection:使用Ultralytics框架进行YOLO-World目标检测
  • 区块链用什么编程语言实现?
  • 【网络编程】UDP通信基础模型实现
  • Docker Compose 常用命令详解
  • 超级外链工具,可发9600条优质外链
  • VisionPro二次开发学习笔记13-使用CogToolBlock进行图像交互
  • 比特币价格分析:市场重置完成,下一个目标:70,000 美元
  • 大模型笔记5 Extractive QA任务评估
  • RCE绕过方式
  • Flutter 电视投屏模块
  • 【机器学习】卷积神经网络简介
  • 时间函数链接函数等
  • Android控件(示例)
  • 图论------贝尔曼-福德(Bellman-Ford)算法
  • 带你彻底搞懂useLayoutEffect的使用场景
  • 大厂进阶之二:React高级用法HOC、Hooks对比、异步组件
  • 【扒代码】ope.py
  • 【Rust光年纪】探索Rust终端编程:从跨平台操作到用户界面设计
  • 67、ceph
  • 最大正方形[中等]
  • JavaScript 浅谈观察者模式 前端设计模式
  • 【自动驾驶】自定义消息格式的话题通信(C++版本)
  • 提升前端性能的JavaScript技巧
  • “服务之巅:Spring Cloud中SLA监控与管理的艺术“