Flutter未来任务管理插件future_manager的使用

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

Flutter未来任务管理插件future_manager的使用

FutureManager

FutureManager 是一个类似于 ValueNotifier 和 ValueListenableBuilder 的库,但它用于处理异步值。它可以帮助开发者更方便地管理和响应 Future 类型的数据变化。

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  future_manager: ^1.11.0

使用场景和动机

当你需要从 API 获取数据或处理会反映到 UI 的 Future 函数时,通常可以使用 setStateFutureBuilder 来处理这种情况。但是这两种方法都会创建样板代码,并且缺乏一些功能,如刷新、事件回调等。而 FutureManager 提供了一种解决方案,主要关注 Future 值的三个状态:加载中(Loading)错误(Error)完成(Done),你可以通过 FutureManagerBuilder 来处理这些状态并更新 UI。

简短示例

下面是一个简短的示例,展示了如何使用 FutureManager 来管理异步数据:

FutureManager<int> dataManager = FutureManager();

@override
void initState() {
  dataManager.execute(() => Future.value(2));
  super.initState();
}

@override
void dispose() {
  dataManager.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return FutureManagerBuilder<int>(
    futureManager: dataManager,
    ready: (context, data) {
      return ElevatedButton(
        child: Text("My data: $data"),
        onPressed: () {
          dataManager.refresh();
        },
      );
    },
  );
}

FutureManager 属性与字段

Property description default
futureFunction 一个函数,用于执行并返回数据 null
reloading 在调用 refreshexecute 时是否重置状态为加载中 true
onSuccess 成功后调用的回调函数 null
onDone 操作完全完成后调用的回调函数,类似于 try-catch 中的 finally null
onError 发生错误时调用的回调函数 null
cacheOption 缓存选项 non
field description
data 当前 Manager 中的数据
error Manager 中的错误
hasData 检查 Manager 是否有数据
hasError 检查 Manager 是否有错误
future 当前 futureFunction 的 Future 对象
isRefreshing 检查 Manager 是否正在刷新

方法

Method description
when 类似于 FutureManagerBuilder 的方法
execute 执行 futureFunction 并将结果存储到 Manager 中
refresh 再次调用 execute,需先通过构造函数分配 futureFunction 或调用一次 execute 方法
updateData 更新 Manager 中的数据
modifyData 使用数据回调更新 Manager 中的数据,推荐使用此方法
resetData 将所有内容重置为加载中或空状态
addError 向 Manager 中添加错误
clearError 清除 Manager 中的错误,但仅在 ViewState 不是错误状态时有效

FutureManagerBuilder

FutureManagerBuilder 是一个用于构建 UI 的小部件,可以根据 FutureManager 的状态来显示不同的 UI 元素。

示例

以下是一个完整的示例,展示了如何使用 FutureManagerBuilder 来管理异步数据并在 UI 中展示:

class _HomePageState extends State<NewPage> {

  FutureManager<int> dataManager = FutureManager();
  
  @override
  void initState() {
    dataManager.execute(() async {
      await Future.delayed(Duration(seconds: 2));
      // 将 10 添加到 dataManager 中
      return 10;
    });
    super.initState();
  }

  @override
  void dispose() {
    dataManager.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 使用 FutureManagerBuilder 构建 UI
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: () {
              // 再次调用 execute
              dataManager.refresh();
            },
          )
        ]
      ),
      body: FutureManagerBuilder<int>(
        futureManager: dataManager,
        error: (error) => YourErrorWidget(),
        loading: YourLoadingWidget(),
        ready: (context, data) {
          // 结果: My data: 10
          return Text("My data: ${data}");
        }
      ),
    );
  }
}

文档

Property description default
futureManager 我们的 FutureManager 对象 required
ready 当 [FutureManager] 有数据时显示的小部件 required
loading 当 [FutureManager] 状态为加载中时显示的小部件 CircularProgressIndicator
error 当 [FutureManager] 状态为错误时显示的小部件 Text(error.toString())
onError 当 [FutureManager] 状态为错误时调用的回调函数 null
onData 当 [FutureManager] 有数据或数据更新时调用的回调函数 null
readyOnce 当 [FutureManager] 首次接收到数据时调用的回调函数 null
onRefreshing 刷新时显示的小部件 null

生态系统和使用

  • 何时使用 cacheOption
    • 当你有一个全局的 Manager 并希望在一段时间内保留数据而不重新执行 execute 逻辑或 futureFunction。
  • 何时使用 ManagerProvider
    • 当你需要在一个非全局范围内跨多个小部件使用 FutureManager 时,而不是将其声明为全局变量。这样做时,FutureManager 将在首次使用时自动销毁并重新创建,类似于 RiverPod 的 autoDispose 功能。

完整示例代码

以下是一个完整的应用示例,展示了如何结合 FutureManagerProviderFutureManager 来构建一个简单的 Flutter 应用程序:

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureManagerProvider(
      onFutureManagerError: (error, context) {
        print("On FutureManager error called: $error");
      },
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Future Manager Example',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(
          dataManager: () => FutureManager(
            reloading: true,
            cacheOption: const ManagerCacheOption.non(),
          ),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final FutureManager Function() dataManager;

  const MyHomePage({Key? key, required this.dataManager}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late FutureManager<int> _dataManager;

  @override
  void initState() {
    _dataManager = widget.dataManager();
    _dataManager.execute(() async {
      await Future.delayed(Duration(seconds: 2));
      return 10;
    });
    super.initState();
  }

  @override
  void dispose() {
    _dataManager.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Future Manager Example'),
        actions: [
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: () {
              _dataManager.refresh();
            },
          )
        ],
      ),
      body: FutureManagerBuilder<int>(
        futureManager: _dataManager,
        loading: Center(child: CircularProgressIndicator()),
        error: (error) => Center(child: Text('Error: $error')),
        ready: (context, data) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  "My data: $data",
                  style: Theme.of(context).textTheme.headline4,
                ),
                ElevatedButton(
                  onPressed: () {
                    _dataManager.refresh();
                  },
                  child: Text('Refresh Data'),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

这个示例展示了如何使用 FutureManagerFutureManagerBuilder 来管理异步数据,并根据数据的状态动态更新 UI。此外,还展示了如何使用 FutureManagerProvider 来提供全局的错误处理机制。


更多关于Flutter未来任务管理插件future_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter未来任务管理插件future_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用future_manager插件进行未来任务管理的代码示例。future_manager插件可以帮助你更好地管理和取消异步任务,特别是在处理网络请求或耗时操作时非常有用。

首先,你需要在你的pubspec.yaml文件中添加future_manager依赖:

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

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

接下来,让我们看一个完整的代码示例,展示如何使用future_manager进行任务管理。

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

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

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

class FutureManagerExample extends StatefulWidget {
  @override
  _FutureManagerExampleState createState() => _FutureManagerExampleState();
}

class _FutureManagerExampleState extends State<FutureManagerExample> {
  final FutureManager<String> futureManager = FutureManager<String>();

  void startTask() {
    // 模拟一个耗时任务,例如网络请求
    futureManager.run(() async {
      await Future.delayed(Duration(seconds: 3));
      return "Task Completed!";
    });
  }

  void cancelTask() {
    // 取消任务
    futureManager.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: startTask,
            child: Text('Start Task'),
          ),
          SizedBox(height: 16),
          ElevatedButton(
            onPressed: cancelTask,
            child: Text('Cancel Task'),
            style: ButtonStyle(
              foregroundColor: MaterialStateProperty.all(Colors.red),
            ),
          ),
          SizedBox(height: 16),
          FutureBuilder<String>(
            future: futureManager.future,
            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('Result: ${snapshot.data}');
              } else {
                return Text('No data');
              }
            },
          ),
        ],
      ),
    );
  }
}

解释

  1. 依赖导入:在pubspec.yaml文件中添加future_manager依赖。

  2. FutureManager实例:在_FutureManagerExampleState类中,我们创建了一个FutureManager<String>实例,用于管理未来的任务。

  3. 启动任务startTask方法使用futureManager.run来启动一个模拟的耗时任务。这个任务在3秒后完成,并返回一个字符串结果。

  4. 取消任务cancelTask方法调用futureManager.cancel来取消当前的任务。

  5. FutureBuilder:使用FutureBuilder来显示任务的状态。当任务正在进行时,显示一个进度指示器;当任务完成时,显示结果;如果发生错误,显示错误信息。

这个示例展示了如何使用future_manager来启动、取消和监听异步任务的状态。希望这对你有所帮助!

回到顶部