Flutter状态管理插件flutter_recoil的使用

Flutter状态管理插件flutter_recoil的使用

▶ Flutter Recoil ◀

centered image

一个帮助实现React Recoil模式的Flutter插件。
更多关于Recoil的信息请访问RecoilJS官方网站。

特性

  • 实现AtomSelector
  • 使用useRecoilSelectorStateuseRecoilState管理Recoil状态
  • 管理Atomeffects列表

开始使用

参见example/lib/recoil/atoms.dart了解如何创建AtomSelector,以及example/lib/main.dart查看完整的示例用法。

使用方法

首先创建AtomSelector来管理Recoil状态。

final checkBoxAtom = Atom<List<CheckBoxModel>>(
  key: 'check_box',
  defaultValue: initialCheckBox,
);

final checkBoxSelector = Selector<List<String>>(
  key: 'check_box_selector',
  getValue: (getValue) => (getValue(checkBoxAtom).value as List<CheckBoxModel>)
      .where((e) => e.value)
      .map((e) => e.id.toString())
      .toList(),
);

为了监听AtomSelector的状态变化,提供了相应的useRecoilStateuseRecoilSelectorState方法。

final checkBox = useRecoilState(checkBoxAtom);

final checkBoxValue = useRecoilSelectorState(checkBoxSelector);

为了使用Atom的效果,提供了setItemDataonItemSet方法。

类和小部件

RecoilWidget

一个可以使用AtomSelector的小部件。它的使用方式类似于StatelessWidget,只实现了build方法。
使用AtomSelector的小部件必须继承自RecoilWidget

RecoilStateStore<T>

管理和评估AtomSelector的值。

RecoilProvider<T>

使用RecoilStateStore提供Recoil上下文。

重要的是,要使用RecoilProvider的builder方法包装需要Recoil上下文的小部件:

[@override](/user/override)
Widget build(BuildContext context) {
 return RecoilProvider(
   builder: (context, child) {
     return YourWidget(
       // 小部件参数
     );
   },
 );
}

Atom<T>

创建一个Atom,它表示一个可写的状态。

  • 定义一个唯一的key以标识相对应的Atom
  • 使用defaultValue设置Atom的初始值
  • 使用effects添加自定义操作到Atom

T类型的值代表onItemSet,每次Atom的值发生变化时都会被调用。
ValueNotifier<T>类型代表setItemData,用于更改当前Atom的值。

可以创建一个效果数组给Atom不同的动作:

final fooAtom = Atom(
  key: 'foo_atom_key',
  defaultValue: initialValue,
  effects: [
    (onItemSet, setItemData) {
      // 第一个效果
    },
    (onItemSet, setItemData) {
      // 第二个效果
    },
  ],
);

Selector<T>

创建一个Selector,它表示一个可读的状态。

  • 定义一个唯一的key以标识相对应的Atom
  • 使用getValue获取一个可读的Atom值。 getValue的返回类型是动态的,所以确保通过从哪个Atom中读取来强制转换。 这是因为在一个Selector中可以从不同的Atom中获取值。
final fooSelector = Selector(
  key: 'foo_selector_key',
  getValue: (getValue) {
    final value = getValue(fooAtom) as YourAtomType;
    // 操作你的值
    return manipulatedValue;
  },
);

useRecoilState()

返回一个自定义的ValueNotifier(参见RecoilNotifier<T>)并订阅组件到该状态的未来更新。

final value = useRecoilState(myAtom);

RecoilNotifier<T>

它是useRecoilState()的返回类型,提供参数用于读取和操作Atom的状态。

  • data可以用来获取Atom的值
  • setData可以用来改变Atom的值

useRecoilSelectorState()

返回Selector的值,并订阅组件到相关的Atom状态的未来更新。

final value = useRecoilSelectorState(mySelector);

许可证

MIT


完整示例

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

import 'recoil/atoms.dart';

void main() => runApp(const MyApp());

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return RecoilProvider(
      builder: (context, child) {
        return const MaterialApp(
          title: 'Flutter Recoil Demo',
          home: MyHomePage(),
          debugShowCheckedModeBanner: false,
        );
      },
    );
  }
}

class CheckBoxModel {
  final int id;
  final bool value;

  CheckBoxModel(this.id, this.value);
}

class MyHomePage extends RecoilWidget {
  const MyHomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final checkBox = useRecoilState(checkBoxAtom);

    void onTileTap(int checkBoxID) => checkBox.setData(
        checkBox.data.map((e) => e.id == checkBoxID ? CheckBoxModel(e.id, !e.value) : e).toList());

    return Scaffold(
      appBar: AppBar(
        title: const Text('Check box'),
      ),
      body: Center(
        child: ListView.separated(
          separatorBuilder: (context, index) => const Divider(
            color: Colors.grey,
            height: 0,
          ),
          itemCount: initialCheckBox.length,
          itemBuilder: (context, index) {
            final currentCheckBox = checkBox.data[index];

            return ListTile(
              title: Text(currentCheckBox.id.toString()),
              trailing: Checkbox(
                value: currentCheckBox.value,
                onChanged: (_) => onTileTap(currentCheckBox.id),
              ),
              onTap: () => onTileTap(currentCheckBox.id),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => ResultScreen(
              onPressed: () {
                checkBox.setData(checkBox.data.map((e) => CheckBoxModel(e.id, false)).toList());
              },
            ),
          ),
        ),
        child: const Icon(Icons.arrow_forward_ios_rounded),
      ),
    );
  }
}

class ResultScreen extends RecoilWidget {
  final VoidCallback onPressed;
  const ResultScreen({Key? key, required this.onPressed}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final checkBoxValue = useRecoilSelectorState(checkBoxSelector);

    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: onPressed,
        child: const Icon(Icons.do_not_disturb_alt_rounded),
        tooltip: "Disable all check box",
      ),
      appBar: AppBar(
        title: const Text('Check box result'),
      ),
      body: Center(
        child: Text(
          "The selected check box are: \n $checkBoxValue",
          textAlign: TextAlign.center,
        ),
      ),
    );
  }
}

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

1 回复

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


在Flutter中,flutter_recoil 是一个强大的状态管理库,它基于 Recoil.js 的概念,旨在提供简洁而强大的状态管理解决方案。下面是一个使用 flutter_recoil 的简单示例,包括如何定义原子状态、选择器以及如何在组件中使用这些状态。

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

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

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

1. 定义原子状态(Atom)

首先,我们需要定义一个原子状态。原子状态是 Recoil 中存储数据的基本单位。

import 'package:flutter_recoil/flutter_recoil.dart';

// 定义一个原子状态来存储计数器的值
final counterAtom = Atom<int>(
  key: 'counterAtom',
  default: 0,
);

2. 定义选择器(Selector)

选择器允许我们基于原子状态派生新的状态。它们对于计算值或转换数据非常有用。

// 定义一个选择器来返回计数器的字符串表示
final counterStringSelector = Selector<String>({
  required Atom<int> counter,
}) => counter.value.toString();

3. 在组件中使用 Recoil

现在,我们可以在 Flutter 组件中使用这些状态和选择器。

import 'package:flutter/material.dart';
import 'package:flutter_recoil/flutter_recoil.dart';
import 'path_to_your_atoms_and_selectors.dart'; // 导入你定义的原子状态和选择器

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RecoilProvider(
      children: [
        MaterialApp(
          home: CounterScreen(),
        ),
      ],
    );
  }
}

class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Recoil Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 使用 RecoilController 来读取和更新原子状态
            RecoilController(
              atom: counterAtom,
              read: (context, value) {
                return Text(
                  'Counter: $value',
                  style: TextStyle(fontSize: 24),
                );
              },
              write: (context, setValue) {
                return ElevatedButton(
                  onPressed: () {
                    setValue((prev) => prev + 1);
                  },
                  child: Text('Increment'),
                );
              },
            ),
            // 使用选择器来显示计数器的字符串表示
            RecoilValue<String>(
              selector: counterStringSelector,
              builder: (context, value) {
                return Text(
                  'Counter as String: $value',
                  style: TextStyle(fontSize: 20, color: Colors.grey),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们:

  1. 使用 Atom 定义了一个计数器状态 counterAtom
  2. 使用 Selector 定义了一个选择器 counterStringSelector,它将计数器的值转换为字符串。
  3. CounterScreen 中,我们使用 RecoilController 来读取和更新计数器状态,并使用 RecoilValue 来显示计数器的字符串表示。

这个示例展示了如何在 Flutter 应用中使用 flutter_recoil 进行状态管理。根据你的需求,你可以进一步扩展和自定义这些状态和选择器。

回到顶部