Flutter异步状态管理插件async_state_builder的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter 异步状态管理插件 async_state_builder 的使用

async_state_builder 提供了轻量级的小部件来使用状态机和模式匹配处理异步数据。这个包是标准 StreamBuilderFutureBuilder 小部件的一个改进版本,使得管理和响应异步计算的各种状态变得更加容易。

使用状态机的好处

使用状态机而不是在 StreamBuilder/FutureBuilder 中使用的传统条件逻辑有几个优点:

  • 可读性:模式匹配提供了清晰简洁的方式来处理各种状态,使代码更易于阅读和理解。
  • 可维护性:状态机将状态逻辑与用户界面分离,使代码更易于维护和扩展。
  • 可靠性:明确定义的状态减少了遇到意外状态或转换的可能性,提高了代码的健壮性。

使用方法

StreamStateMachineBuilder

StreamStateMachineBuilder<int>(
    stream: stream,
    builder: (BuildContext context, StreamState<int> state) {
        return switch (state) {
            Waiting() => const Text('Waiting for data...'),
            Data<int>(:final data) => Text('Data: $data'),
            Closed<int>(:final data?) => Text('Closed, data received before closing: $data'),
            Closed<int>() => const Text('Closed before any data was sent'),
            StreamStateMachineError<int>(:final data?, :final error) => Text('Error, data received before error: $data. Error: $error'),
            StreamStateMachineError<int>(:final error) => Text('Error received before any data was sent. Error: $error'),
        };
    },
),

你也可以只针对你关心的状态进行编程:

switch (state) {
    Waiting() => const Text('Waiting for data...'),
    Data<int>(:final data) => Text('Data: $data'),
    _ => Text('Unexpected state'),
};

StreamStateBuilder

StreamStateBuilder<int>(
    stream: stream,
    builder: (BuildContext context, StreamState<int> state) {
        return switch (state) {
            Waiting() => const Text('Waiting for data...'),
            Data<int>(:final data) => Text('Data: $data'),
            StreamError<int>(:final error) => Text('Error: $error'),
        };
    },
),

FutureStateBuilder

FutureStateBuilder<int>(
    future: future,
    builder: (BuildContext context, FutureState<int> state) {
        return switch (state) {
            Waiting() => const Text('Waiting to finish...'),
            Data<int>(:final data) => Text('Data: $data'),
            FutureError<int>(:final error) => Text('Error: $error'),
        };
    },
)

完整示例

以下是一个完整的示例,展示了如何使用 StreamStateMachineBuilder 来管理异步数据流的状态。

import 'dart:async';
import 'package:async_state_builder/async_state_builder.dart';
import 'package:flutter/material.dart';

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: CounterPage(),
    );
  }
}

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

  [@override](/user/override)
  CounterPageState createState() => CounterPageState();
}

class CounterPageState extends State<CounterPage> {
  StreamController<int> _counterController = StreamController<int>();
  int _counter = 0;
  bool _hasWaitedTooLong = false;

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  void _incrementCounter() {
    _counter++;
    _counterController.add(_counter);
  }

  void _closeStream() {
    _counterController.close();
  }

  void _sendError() {
    _counterController.addError('An error occurred!');
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('StreamStateBuilder example'),
      ),
      body: _hasWaitedTooLong
          ? const Center(child: Text("Waited too long, callback invoked"))
          : StreamStateMachineBuilder<int>(
              stream: _counterController.stream,
              waitingTimeoutAction:
                  WaitingTimeoutCallback(const Duration(seconds: 5), () {
                setState(() {
                  _hasWaitedTooLong = true;
                });
              }),
              builder:
                  (BuildContext context, StreamStateMachineState<int> state) {
                return Center(
                    child: switch (state) {
                  Waiting() => const Text('Waiting for data...'),
                  StreamStateMachineError<int>(:final data?, :final error) =>
                    Text(
                        'Error, data received before error: $data. Error: $error'),
                  Closed<int>(:final data?) => 
                    Text('Closed, data received before closing: $data'),
                  Data<int>(:final data) => 
                    Text('Data sent without error: $data'),
                  StreamStateMachineError<int>(:final error) => Text(
                      'Error received before any data was sent. Error: $error'),
                  Closed<int>() => 
                    const Text('Stream closed, before any data was sent'),
                });
              },
            ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () {
              setState(() {
                _counterController.close();
                _counterController = StreamController();
                _counter = 0;
                _hasWaitedTooLong = false;
              });
            },
            tooltip: 'Restart',
            child: const Icon(Icons.refresh),
          ),
          const SizedBox(height: 10),
          FloatingActionButton(
            onPressed: () {
              setState(() {});
            },
            tooltip: 'Trigger rebuild',
            child: const Icon(Icons.build),
          ),
          const SizedBox(height: 10),
          FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Send Data',
            child: const Icon(Icons.add),
          ),
          const SizedBox(height: 10),
          FloatingActionButton(
            onPressed: _sendError,
            tooltip: 'Send Error',
            child: const Icon(Icons.error),
          ),
          const SizedBox(height: 10),
          FloatingActionButton(
            onPressed: _closeStream,
            tooltip: 'Close Stream',
            backgroundColor: Colors.red,
            child: const Icon(Icons.close),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter异步状态管理插件async_state_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter异步状态管理插件async_state_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,async_state_builder 是一个用于 Flutter 的异步状态管理插件,它简化了在 UI 中处理异步数据的工作流程。以下是一个如何使用 async_state_builder 的代码示例。

首先,确保在你的 pubspec.yaml 文件中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  async_state_builder: ^x.y.z # 请替换为最新版本号

然后运行 flutter pub get 以安装依赖。

下面是一个完整的 Flutter 应用示例,展示如何使用 async_state_builder 来管理异步状态:

import 'package:flutter/material.dart';
import 'package:async_state_builder/async_state_builder.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Async State Builder Example'),
        ),
        body: Center(
          child: AsyncStateBuilder<String>(
            future: _fetchData(),
            builder: (context, state) {
              if (state.isLoading) {
                return CircularProgressIndicator();
              } else if (state.hasError) {
                return Text('Error: ${state.error}');
              } else if (state.hasData) {
                return Text('Data: ${state.data}');
              } else {
                // This state should not be reached if future is properly defined
                return Text('No Data');
              }
            },
          ),
        ),
      ),
    );
  }

  Future<String> _fetchData() async {
    // Simulate a network request with a delay
    await Future.delayed(Duration(seconds: 2));
    return 'Hello, Flutter!';
  }
}

在这个示例中,我们创建了一个简单的 Flutter 应用,它包含一个使用 AsyncStateBuilderScaffoldAsyncStateBuilder 接受一个 future 和一个 builder 函数。

  • future 是一个返回异步数据的 Future
  • builder 函数根据 AsyncState 的不同状态(加载中、有错误、有数据)返回不同的 UI。

_fetchData 函数模拟了一个网络请求,使用 Future.delayed 来模拟延迟。

AsyncStateBuilder 开始构建时,它首先显示一个 CircularProgressIndicator,因为 future 还没有完成。2 秒后,future 完成,AsyncStateBuilder 显示获取到的数据。如果 future 过程中发生错误,它会显示错误信息。

这个示例展示了如何使用 async_state_builder 插件来简化异步状态管理,使代码更加简洁和易于维护。

回到顶部