一、Future 和 Stream 是处理异步操作的两个重要概念:
Future:
Future 用于表示一个延迟操作的值或错误,即异步操作的结果。通过 Future,可以在异步操作完成后获取其结果。可以使用 async 和 await 关键字来处理 Future,使得异步操作更加直观和易于管理。
Stream:
Stream 则用于处理一系列异步数据(事件)的序列。它可以持续地产生数据,而不是单一的结果。Stream 可以用于处理事件、文件读写、状态管理等需求。使用 StreamController 可以很好的控制 Stream 的创建和数据添加。
二、Future的使用:
async 和 await。
async:用于在方法或函数声明前添加,表示该方法是一个异步方法。在异步方法中,执行顺序可以是非阻塞的,不会阻塞当前线程。
await:用于在异步方法中等待并获取异步表达式的执行结果,只能在被 async 修饰的方法中使用。
1、模拟一个异步请求数据的实现
通过async关键字声明一个异步方法,延迟2秒后返回模拟的结果String值。
Future<String> getAsyncData() async {
    setState(() {
      asyncData = "开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 2));
    return "返回:Future get async data.";
} 
通过按钮点击触发模拟接口请求,获取到异步数据后更新到页面中。
ElevatedButton(
  onPressed: () {
	getAsyncData().then((value) {
	  setState(() {
		asyncData = value;
	  });
	});
  },
  child: const Text("Future get async data.")),
Text(asyncData), 

2、模拟两个异步请求并行,待全部接口请求完成后获取数据的实现
通过async关键字声明两个异步方法,分别延迟2秒和延迟3秒后,返回模拟的结果String值。
Future<String> getAsyncData2() async {
    setState(() {
      asyncTowData = "getAsyncData2开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 2));
    setState(() {
      asyncTowData = "getAsyncData2完成请求数据";
    });
    return "延迟2秒返回";
}
Future<int> getAsyncData3() async {
    setState(() {
      asyncTowData = "getAsyncData3开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 3));
    setState(() {
      asyncTowData = "getAsyncData3完成请求数据";
    });
    return 3;
} 
创建第三个异步方法,将上面的两个异步方法添加到数组里面,并行执行。
// 同时执行两个异步方法并等待它们的结果
Future<List<dynamic>> getTowAsyncData() async {
    List<Future<dynamic>> futures = [getAsyncData2(), getAsyncData3()];
    List<dynamic> result = await Future.wait(futures);
    return result;
} 
通过按钮点击触发模拟接口请求,获取到异步数据后更新到页面中。
ElevatedButton(
  onPressed: () {
	getTowAsyncData().then((value) {
	  var data1 = value[0] as String;
	  var data2 = value[1] as int;
	  setState(() {
		asyncTowData = "$data1,延迟$data2秒返回";
	  });
	});
  },
  child: const Text("Future get tow async data.")),
Text(asyncTowData), 

3、FutureBuilder 使用
通过FutureBuilder实现请求数据时展示加载组件,请求成功后显示数据。
Widget _init() {
    return FutureBuilder(
      future: initAsyncData(),
      builder: (context, snapshot) {
        // 等待状态显示的widget
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(
            child: CircularProgressIndicator(),
          );
          //  错误时显示的widget
        } else if (snapshot.hasError) {
          return const Text('Error');
          // 加载完成后显示的数据
        } else {
          return _widget();
        }
      },
    );
} 

4、FuturePage完整代码
import 'package:flutter/material.dart';
///create by itz on 2024/8/16 14:55
///desc : 
class FuturePage extends StatefulWidget {
  const FuturePage({super.key});
  @override
  State<FuturePage> createState() => _FuturePageState();
}
class _FuturePageState extends State<FuturePage> {
  String asyncData = "";
  String asyncTowData = "";
  bool isInit = false;
  Future initAsyncData() async {
    await Future.delayed(const Duration(seconds: 2));
    isInit = true;
  }
  Future<String> getAsyncData() async {
    setState(() {
      asyncData = "开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 2));
    return "返回:Future get async data.";
  }
  Future<String> getAsyncData2() async {
    setState(() {
      asyncTowData = "getAsyncData2开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 2));
    setState(() {
      asyncTowData = "getAsyncData2完成请求数据";
    });
    return "延迟2秒返回";
  }
  Future<int> getAsyncData3() async {
    setState(() {
      asyncTowData = "getAsyncData3开始请求数据";
    });
    await Future.delayed(const Duration(seconds: 3));
    setState(() {
      asyncTowData = "getAsyncData3完成请求数据";
    });
    return 3;
  }
  // 同时执行两个异步方法并等待它们的结果
  Future<List<dynamic>> getTowAsyncData() async {
    List<Future<dynamic>> futures = [getAsyncData2(), getAsyncData3()];
    List<dynamic> result = await Future.wait(futures);
    return result;
  }
  @override
  Widget build(BuildContext context) {
    Widget w = isInit ? _widget() : _init();
    return Scaffold(
      appBar: AppBar(
        title: const Text("Future"),
      ),
      body: w,
    );
  }
  Widget _init() {
    return FutureBuilder(
      future: initAsyncData(),
      builder: (context, snapshot) {
        // 等待状态显示的widget
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(
            child: CircularProgressIndicator(),
          );
          //  错误时显示的widget
        } else if (snapshot.hasError) {
          return const Text('Error');
          // 加载完成后显示的数据
        } else {
          return _widget();
        }
      },
    );
  }
  Widget _widget() {
    return Container(
      margin: const EdgeInsets.all(16),
      child: ListView(
        children: [
          ElevatedButton(
              onPressed: () {
                getAsyncData().then((value) {
                  setState(() {
                    asyncData = value;
                  });
                });
              },
              child: const Text("Future get async data.")),
          Text(asyncData),
          const SizedBox(height: 10),
          ElevatedButton(
              onPressed: () {
                getTowAsyncData().then((value) {
                  var data1 = value[0] as String;
                  var data2 = value[1] as int;
                  setState(() {
                    asyncTowData = "$data1,延迟$data2秒返回";
                  });
                });
              },
              child: const Text("Future get tow async data.")),
          Text(asyncTowData),
        ],
      ),
    );
  }
}
 
三、Stream的使用
在Flutter中,Stream 是用于处理异步事件序列的概念,常见应用包括:
异步数据获取:Stream在异步数据获取方面非常有用。例如,在网络请求中,可以使用 Stream 来处理异步数据的传输和响应。通过监听 Stream,可以实时获取数据并更新应用程序的界面,实现动态数据展示的功能。
状态管理:Stream在状态管理中扮演着重要的角色。通过创建包含状态信息的 Stream,可以在应用程序中管理状态的变化。当状态发生变化时,通过 Stream 向订阅者(监听者)发送新的状态信息,从而触发相应的操作或界面更新。
事件总线:Stream可以作为事件总线,用于在应用程序中处理和传递事件。通过创建一个全局的 Stream,不同部分的应用程序可以监听并发送事件,实现模块之间的通信和交互。这种方式可以实现解耦和灵活的组件通信。
文件读写:Stream`也可以用于处理文件读写操作。例如,读取大文件时可以使用 Stream实现分块读取,提高读取效率。同样,可以通过 Stream 监听文件写入事件,实现实时监控文件变化等功能。
1、异步数据获取
1)创建StreamController 控制器,控制 Stream 的创建、数据添加 和 关闭等操作。
final StreamController _streamController = StreamController(); 
2)创建异步方法,模拟异步数据获取
getStreamData() async {
    for (int i = 0; i < 10; i++) {
      await Future.delayed(const Duration(seconds: 1));
      // 发送值
      _streamController.sink.add(i);
    }
    await Future.delayed(const Duration(seconds: 1));
    // 发送值
    _streamController.sink.add("done");
} 
3)创建StreamBuilder用于接收流式数据
StreamBuilder(
  stream: _streamController.stream,
  builder: (context, snapshot) {
	if (snapshot.hasData) {
	  return Text('异步数据:${snapshot.data}');
	} else if (snapshot.hasError) {
	  return Text('发生错误:${snapshot.error}');
	} else {
	  return const Text('加载中...');
	}
  }) 
4)通过按钮点击触发模拟接口请求
ElevatedButton(
  onPressed: () {
	getStreamData();
  },
  child: const Text("stream get async data.")), 


5)完整代码
/*年轻人,只管向前看,不要管自暴自弃者的话*/
import 'dart:async';
import 'package:flutter/material.dart';
///create by itz on 2024/8/16 15:46
///desc :
class StreamPage extends StatefulWidget {
  const StreamPage({super.key});
  @override
  State<StreamPage> createState() => _StreamPageState();
}
class _StreamPageState extends State<StreamPage> {
  // 创建控制器
  final StreamController _streamController = StreamController();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Stream"),
      ),
      body: _widget(),
    );
  }
  Widget _widget() {
    return Container(
      margin: const EdgeInsets.all(16),
      child: ListView(
        children: [
          ElevatedButton(
              onPressed: () {
                getStreamData();
              },
              child: const Text("stream get async data.")),
          StreamBuilder(
              stream: _streamController.stream,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return Text('异步数据:${snapshot.data}');
                } else if (snapshot.hasError) {
                  return Text('发生错误:${snapshot.error}');
                } else {
                  return const Text('加载中...');
                }
              })
        ],
      ),
    );
  }
  getStreamData() async {
    for (int i = 0; i < 10; i++) {
      await Future.delayed(const Duration(seconds: 1));
      // 发送值
      _streamController.sink.add(i);
    }
    await Future.delayed(const Duration(seconds: 1));
    // 发送值
    _streamController.sink.add("done");
  }
}
 
2、事件总线
1)创建EventBus单例类
import 'dart:async';
///create by itz on 2024/8/16 15:54
///desc :
class EventBus {
  static final EventBus _instance = EventBus._internal();
  factory EventBus() => _instance;
  EventBus._internal();
} 
2)使用 broadcast() 方法创建了一个可以实时广播事件的 StreamController
final _controller = StreamController<dynamic>.broadcast(); 
3)创建 get stream,发送事件,关闭控制器等方法
  Stream get stream => _controller.stream;
  void fire(dynamic event) {
    _controller.sink.add(event);
  }
  void dispose() {
    _controller.close();
  } 
4)使用EventBus,设置EventBus事件监听
    EventBus().stream.listen((event) {
      setState(() {
        eventInfo = event;
      });
    }); 
5)发送EventBus事件
sendEvent(String event) {
    EventBus().fire(event);
  } 
6)通过按钮点击触发发送事件
ElevatedButton(
	onPressed: () {
	  sendEvent("cat");
	},
	child: const Text("send Event.")),
Text(eventInfo), 

7)完整EventBus代码
import 'dart:async';
///create by itz on 2024/8/16 15:54
///desc :
class EventBus {
  static final EventBus _instance = EventBus._internal();
  factory EventBus() => _instance;
  EventBus._internal();
  // 使用 broadcast() 方法创建了一个可以实时广播事件的 StreamController
  final _controller = StreamController<dynamic>.broadcast();
  Stream get stream => _controller.stream;
  void fire(dynamic event) {
    _controller.sink.add(event);
  }
  void dispose() {
    _controller.close();
  }
} 
8)完整EventBusPage代码
import 'package:async_test/util/EventBus.dart';
import 'package:flutter/material.dart';
///create by itz on 2024/8/16 16:01
///desc :
class EventBusPage extends StatefulWidget {
  const EventBusPage({super.key});
  @override
  State<EventBusPage> createState() => _EventBusPageState();
}
class _EventBusPageState extends State<EventBusPage> {
  String eventInfo = "";
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    EventBus().stream.listen((event) {
      setState(() {
        eventInfo = event;
      });
    });
  }
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    EventBus().dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("EventBus"),
      ),
      body: Container(
        margin: const EdgeInsets.all(16),
        child: ListView(
          children: [
            ElevatedButton(
                onPressed: () {
                  sendEvent("cat");
                },
                child: const Text("send Event.")),
            Text(eventInfo),
          ],
        ),
      ),
    );
  }
  sendEvent(String event) {
    EventBus().fire(event);
  }
} 
Stream 适用于处理持续产生数据的异步操作,而 async/await 适用于一次性获取结果的异步操作。两者使用区别包括控制流、数据处理、使用场景和代码结构。
Provider 与 Stream 区别在于使用 Provider 时状态可以被存储起来,而 Stream 不会存储。选择使用哪种取决于需求和代码结构的复杂度。









