Flutter异步阶段通知插件async_phase_notifier的使用

Flutter异步阶段通知插件async_phase_notifier的使用

async_phase_notifier 是一个基于 ValueNotifier 的变种,用于表示异步操作的初始、等待、完成或错误阶段。它类似于 Riverpod 中的 AsyncNotifierAsyncValue,但与 Riverpod 没有绑定关系。

样例应用

使用方法

更新方法 update()

AsyncPhaseNotifierupdate() 方法执行一个异步函数,并根据异步操作的阶段自动更新 AsyncPhaseNotifier 的值,同时通知监听器。

  1. 当操作开始时,通知器的值切换到 AsyncWaiting
  2. 通知监听器。
  3. 根据结果,值切换到 AsyncCompleteAsyncError
  4. 通知监听器。
final notifier = AsyncPhaseNotifier(0);
notifier.update(() => someAsyncOperation());

更新仅限于阶段 updateOnlyPhase()

该方法与 update() 类似,但只更新阶段而不更新 value.data。此方法适用于在执行过程中需要更新阶段,但回调结果不应影响数据的情况。

notifier.updateOnlyPhase(() => someAsyncOperation());

异步阶段 AsyncPhase

AsyncPhaseNotifier 的值可以是 AsyncInitialAsyncWaitingAsyncCompleteAsyncError。这些类型都是 AsyncPhase 的子类型。

AsyncPhase 提供了 when()whenOrNull() 方法,可用于根据当前阶段选择相应的操作。

child: phase.when(
  initial: (data) => Text('phase: AsyncInitial($data)'), // 可选
  waiting: (data) => Text('phase: AsyncWaiting($data)'),
  complete: (data) => Text('phase: AsyncComplete($data)'),
  error: (data, error, stackTrace) => Text('phase: AsyncError($data, $error)'),
)

value.datadata

datavalue.data 的便捷获取器。如果 AsyncPhaseNotifier<T> 的泛型类型 T 是非空的,则返回类型也是非空的,这使得代码更安全。

监听阶段变化

listen()

通过 listen() 方法可以在阶段或其数据发生变化时触发某些动作。

final notifier = AsyncPhaseNotifier(Auth());
final cancel = notifier.listen((phase) { /* 一些动作 */ });

...

// 如果不再需要监听器,则移除它。
cancel();
listenFor()

通过 listenFor() 方法可以在阶段或其数据发生变化时触发某些动作。

final notifier = AsyncPhaseNotifier(Auth());
final cancel = notifier.listenFor(
  onWaiting: (isWaiting) { /* e.g. 切换指示器 */ },
  onComplete: (data) { /* e.g. 记录操作结果 */ }, 
  onError: (e, s) { /* e.g. 显示错误对话框 */ },
);

...

// 如果不再需要监听器,则移除它。
cancel();
AsyncPhaseListener

还可以使用 AsyncPhaseListener 小部件来监听阶段变化。

child: AsyncPhaseListener(
  notifier: notifier,
  onWaiting: (isWaiting) { /* e.g. 切换指示器 */ },
  onComplete: (data) { /* e.g. 记录操作结果 */ },
  onError: (e, s) { /* e.g. 显示错误对话框 */ },
  child: ...,
)

示例

下面是一个 WeatherNotifier 示例,它继承自 AsyncPhaseNotifier 并获取城市天气信息并通知其监听器。

class WeatherNotifier extends AsyncPhaseNotifier<Weather> {
  WeatherNotifier() : super(const Weather());

  final repository = WeatherRepository();

  void fetch() {
    update(() => repository.fetchWeather(Cities.tokyo));
  }
}
final notifier = WeatherNotifier();
notifier.fetch();

使用 ValueListenableBuilder

[@override](/user/override)
Widget build(BuildContext context) {
  return ValueListenableBuilder<AsyncPhase<Weather>>(
    valueListenable: notifier,
    builder: (context, phase, _) {
      return phase.when(
        waiting: (weather) => const CircularProgressIndicator(),
        complete: (weather) => Text('$weather'),
        error: (weather, e, s) => Text('$e'),
      );
    },
  ); 
}

使用 Provider

ValueListenableProvider<AsyncPhase<Weather>>.value(
  value: notifier,
  child: MaterialApp(home: ...),
)
[@override](/user/override)
Widget build(BuildContext context) {
  final phase = context.watch<AsyncPhase<Weather>>();

  return phase.when(
    waiting: (weather) => const CircularProgressIndicator(),
    complete: (weather) => Text('$weather'),
    error: (weather, e, s) => Text('$e'),
  );
}

使用 Grab

void main() {
  runApp(
    const Grab(child: App()),
  ); 
}
[@override](/user/override)
Widget build(BuildContext context) {
  final phase = notifier.grab(context);

  return phase.when(
    waiting: (weather) => const CircularProgressIndicator(),
    complete: (weather) => Text('$weather'),
    error: (weather, e, s) => Text('$e'),
  );
}

更多关于Flutter异步阶段通知插件async_phase_notifier的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter异步阶段通知插件async_phase_notifier的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的async_phase_notifier插件的使用,这里提供一个简单的代码示例来展示其基本用法。async_phase_notifier允许你在异步操作的各个阶段发送通知,这对于长时间运行的任务尤其有用,你可以通知UI进行进度更新或显示加载指示器。

首先,确保你的pubspec.yaml文件中已经添加了async_phase_notifier依赖:

dependencies:
  flutter:
    sdk: flutter
  async_phase_notifier: ^最新版本号 # 替换为实际的最新版本号

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

下面是一个简单的例子,展示如何使用async_phase_notifier来管理一个模拟的长时间异步任务,并在UI中更新进度。

main.dart

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Async Phase Notifier Example'),
        ),
        body: AsyncPhaseNotifierExample(),
      ),
    );
  }
}

class AsyncPhaseNotifierExample extends StatefulWidget {
  @override
  _AsyncPhaseNotifierExampleState createState() => _AsyncPhaseNotifierExampleState();
}

class _AsyncPhaseNotifierExampleState extends State<AsyncPhaseNotifierExample> {
  final AsyncPhaseNotifier<int> _notifier = AsyncPhaseNotifier<int>();

  @override
  void initState() {
    super.initState();
    _startLongRunningTask();
  }

  void _startLongRunningTask() {
    _notifier.start(
      () async {
        for (int i = 0; i <= 100; i += 10) {
          await Future.delayed(Duration(seconds: 1)); // 模拟耗时操作
          _notifier.notifyPhase(i);
        }
        _notifier.complete(100); // 完成最终阶段
      },
      onError: (error, stackTrace) {
        // 处理错误
        print('Error: $error');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        CircularProgressIndicator(
          value: _notifier.progress ?? 0.0,
          valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
        ),
        SizedBox(height: 20),
        Text(
          'Progress: ${_notifier.progress?.toInt() ?? 0}%',
          style: TextStyle(fontSize: 24),
        ),
      ],
    );
  }

  @override
  void dispose() {
    _notifier.dispose(); // 清理资源
    super.dispose();
  }
}

解释

  1. 依赖安装:首先,在pubspec.yaml文件中添加async_phase_notifier依赖。

  2. 创建应用:在main.dart中,创建一个简单的Flutter应用,其中包含一个AsyncPhaseNotifierExample组件。

  3. 状态管理:在_AsyncPhaseNotifierExampleState中,使用AsyncPhaseNotifier<int>来管理异步任务的状态和进度。

  4. 启动任务:在initState方法中,调用_startLongRunningTask函数启动一个模拟的长时间异步任务。这个任务每隔一秒更新一次进度,并通过_notifier.notifyPhase(i)发送进度通知。

  5. UI更新:在build方法中,使用CircularProgressIndicatorText组件来显示当前的进度。CircularProgressIndicatorvalue属性绑定到_notifier.progress,从而根据进度更新UI。

  6. 资源清理:在dispose方法中调用_notifier.dispose()来清理资源,避免内存泄漏。

这个示例展示了如何使用async_phase_notifier来管理和通知异步操作的进度,从而更新UI。你可以根据自己的需求进一步定制和扩展这个示例。

回到顶部