Flutter价值存储与获取插件valuable的使用

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

Flutter价值存储与获取插件Valuable的使用

关于Valuable

什么是Valuable?

Valuable是另一个状态管理库,它从Riverpod中汲取灵感,并且每个Provider-like都是自治的,可以独立工作。它是一个图状态管理库,旨在尽可能多地构建无状态的小部件树,同时能够在不必要将小部件树分割成无限多个StatelessWidget的情况下刷新部分树。

为什么选择Valuable?

  • Riverpod:用于应用的全局状态。
  • Valuable:用于局部状态(如小部件、视图等)。

如何使用Valuable?

声明Valuable

根据需要声明一个Valuable:

  • StatefulValuable<T>:最常见的类型,可以设置值。
  • FutureValuable<Output, Res>:处理Future<Res>并提供Output
  • StreamValuable<Output, Msg>:处理Stream<Msg>并提供Output
  • Valuable<T>:其他情况,可以是不可变值或评估函数。

对所有Valuable的操作

获取当前值

Valuable<T> myValuable = ...;

myValuable.getValue(); // 获取当前值

在某些情况下,getValue需要一个ValuableContext,但通常不是必需的。

监听变化

myValuable.addListener(() {
    // 值发生变化时触发
});

标记为无效

myValuable.markToReevaluate();

比较操作

Valuable重定义了一些常见的比较运算符,例如><<=>=等。

示例:

Valuable<int> a = ...;
Valuable<int> b = ...;

Valuable<bool> equality = a.equals(b);

StatefulValuable<T>

这是最常用的Valuable类型,可以直接设置其值。

实例化

StatefulValuable<int> counter = StatefulValuable<int>(0);

设置值

counter.setValue(1);

FutureValuable<Output, Res>

用于将Valuable<Future<Res>>转换为安全运行时的Output值。

计算构造函数

late final Valuable<Future<int>> distantCounter = ...;
late final FutureValuable<String, int> distantCounterStr = FutureValuable<String, int>(
    distantCounter,
    dataValue: (ValuableContext? context, int result) => "My counter is $result",
    noDataValue: (ValuableContext? context) => "Still in progress",
    errorValue: (ValuableContext? context, Object error, StackTrace st) => "Can't retrieve counter !",
);

StreamValuable<Output, Msg>

类似于FutureValuable,但它处理的是Stream而不是Future

计算构造函数

late final Valuable<Stream<int>> continuousCounter = ...;
late final StreamValuable<String, int> continuousCounterStr = StreamValuable<String, int>(
    continuousCounter,
    dataValue: (ValuableContext? context, int result) => "$result",
    doneValue: (ValuableContext? context) => "Done.",
    errorValue: (ValuableContext? context, Object error, StackTrace st) => "On error !",
    initialValue: "0",
);

Valuable<T>

这是所有Valuable的基类,提供了两个工厂方法:

简单不可变值

final Valuable<int> zero = Valuable.value(0);

自动评估

final StatefulValuable<int> counter = StatefulValuable<int>(2);
final Valuable<double> halfCounter = Valuable.evaluate((ValuableWatcher watch) => watch(counter) / 2);

print(halfCounter.getValue()); // 输出 '1'
counter.setValue(3); // halfCounter 被通知并重新计算
print(halfCounter.getValue()); // 输出 '1.5'

Valuable与Widget树

ValuableConsumer

这是在Widget树中使用Valuable的最常见方式,用于创建响应式UI。

示例:

final StatefulValuable<Color> myColor = StatefulValuable<Color>(Colors.red);

Widget build(BuildContext context) {
    return Column(
        children: <Widget>[
            Container(
                color: Colors.amber,
                width: 100,
                height: 100,
            ),
            ValuableConsumer(
                builder: (BuildContext context, ValuableWatcher watch, _) =>
                    Container(
                        color: watch(myColor),
                        width: 100,
                        height: 100,
                    ),
            ),
            Row(
                children: <Widget>[
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.blue),
                        child: const Text("Blue"),
                    ),
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.red),
                        child: const Text("Red"),
                    ),
                ],
            ),
        ],
    );               
}

ValuableWidget

在某些情况下,你可能希望定义一个依赖于一个或多个Valuable的可重用Widget。

示例:

class ColoredSquare extends ValuableWidget {
    final Valuable<Color> myColor;

    const ColoredSquare({
            required this.myColor,
            Key? key,
        }) : super(key: key);

    Widget build(BuildContext context, ValuableWatcher watch) {
        return Container(
                    color: watch(myColor),
                    width: 100,
                    height: 100,
                );
    }    
}

// 使用
final StatefulValuable<Color> myColor = StatefulValuable<Color>(Colors.red);

Widget build(BuildContext context) {
    return Column(
        children: <Widget>[
            Container(
                color: Colors.amber,
                width: 100,
                height: 100,
            ),
            ColoredSquare(
                myColor: myColor,
            ),
            Row(
                children: <Widget>[
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.blue),
                        child: const Text("Blue"),
                    ),
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.red),
                        child: const Text("Red"),
                    ),
                ],
            ),
        ],
    );               
}

watchIt

这是一个扩展方法,允许从最近的ValuableConsumer中读取值并订阅Valuable的变化。

示例:

final StatefulValuable<Color> myColor = StatefulValuable<Color>(Colors.red);

Widget build(BuildContext context) {
    return Column(
        children: <Widget>[
            Container(
                color: Colors.amber,
                width: 100,
                height: 100,
            ),
            Container(
                    color: myColor.watchIt(context),
                    width: 100,
                    height: 100,
                ),
            ),
            Row(
                children: <Widget>[
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.blue),
                        child: const Text("Blue"),
                    ),
                    TextButton(
                        onPressed: () => myColor.setValue(Colors.red),
                        child: const Text("Red"),
                    ),
                ],
            ),
        ],
    );               
}

完整示例Demo

以下是一个完整的示例,展示了如何使用Valuable来管理颜色状态并在UI中显示:

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  final StatefulValuable<Color> myColor = StatefulValuable<Color>(Colors.red);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Valuable Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              color: Colors.amber,
              width: 100,
              height: 100,
            ),
            ValuableConsumer(
              builder: (BuildContext context, ValuableWatcher watch, _) =>
                  Container(
                    color: watch(myColor),
                    width: 100,
                    height: 100,
                  ),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                TextButton(
                  onPressed: () => myColor.setValue(Colors.blue),
                  child: const Text("Blue"),
                ),
                TextButton(
                  onPressed: () => myColor.setValue(Colors.red),
                  child: const Text("Red"),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter价值存储与获取插件valuable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter价值存储与获取插件valuable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用valuable插件进行值存储与获取的示例代码。valuable插件允许你在Flutter应用中轻松存储和获取全局状态。

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

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

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

接下来是一个完整的示例代码,展示如何使用valuable插件进行值的存储和获取。

主应用代码 (main.dart)

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

void main() {
  // 创建一个全局的Valuable实例
  final valuable = Valuable<String>();

  runApp(MyApp(valuable: valuable));
}

class MyApp extends StatelessWidget {
  final Valuable<String> valuable;

  MyApp({required this.valuable});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Valuable Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(valuable: valuable),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final Valuable<String> valuable;

  MyHomePage({required this.valuable});

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

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Valuable Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TextField(
              controller: _controller,
              decoration: InputDecoration(labelText: 'Enter a value'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                // 存储值
                widget.valuable.value = _controller.text;
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Value stored')),
                );
              },
              child: Text('Store Value'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                // 获取值
                final value = widget.valuable.value;
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text("Current Value: $value")),
                );
              },
              child: Text('Get Value'),
            ),
          ],
        ),
      ),
    );
  }
}

解释

  1. 创建Valuable实例:在main函数中,我们创建了一个全局的Valuable<String>实例。
  2. 传递Valuable实例:我们将Valuable实例传递给MyApp,然后进一步传递给MyHomePage
  3. 存储值:在_MyHomePageStatebuild方法中,我们有一个TextField用于输入值,并通过点击按钮将输入的值存储到Valuable实例中。
  4. 获取值:通过点击另一个按钮,我们从Valuable实例中获取当前存储的值,并通过SnackBar显示出来。

这样,你就可以在Flutter应用中轻松地存储和获取全局状态了。希望这个示例对你有帮助!

回到顶部