Flutter响应式计算值管理插件computed_value_notifier的使用

Flutter响应式计算值管理插件computed_value_notifier的使用

使用

ComputedValueNotifier 可以用来根据另一个 Listenable 或多个 Listenable 的数据派生出一个值。当提供的 listenable 通知监听器其值已更改时,该值将被重新计算。

简单示例

final email = ValueNotifier<String>('a');

// 使用一个(hacky)验证器来确定电子邮件是否有效。
final emailValid = ComputedValueNotifier(
  email,
  () => email.value.contains('@'),
);

// 提供给 ComputedValueNotifier 的函数会立即执行,并且计算出的值可以同步获取。
print(emailValid.value); // 打印 'false'。

// 当 email ValueNotifier 改变时,函数会被再次执行!
email.value = 'a@b.com';
print(emailValid.value); // 打印 'true'。

示例代码

以下是完整的示例代码,展示了如何在实际应用中使用 ComputedValueNotifier

import 'package:flutter/material.dart';

// 定义一个表单视图模型类,用于管理表单字段的状态。
class FormViewModel {
  final email = ValueNotifier<String>('');
  final password = ValueNotifier<String>('');

  // 使用 ComputedValueNotifier 来管理登录按钮是否可点击的状态。
  final canLogin = ComputedValueNotifier(
    [email, password],
    () => email.value.isNotEmpty && password.value.isNotEmpty,
  );

  // 在组件销毁时清理资源。
  void dispose() {
    email.dispose();
    password.dispose();
  }
}

void main(List<String> args) {
  runApp(const ExampleApp());
}

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

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

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

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

class _HomeState extends State<Home> {
  late final FormViewModel formViewModel;

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Computed Value Notifier Example')),
      body: Center(
        child: FractionallySizedBox(
          widthFactor: 0.8,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                decoration: const InputDecoration(hintText: 'Email'),
                onChanged: (newValue) => formViewModel.email.value = newValue,
              ),
              const SizedBox(height: 10),
              TextField(
                obscureText: true,
                decoration: const InputDecoration(hintText: 'Password'),
                onChanged: (newValue) =>
                    formViewModel.password.value = newValue,
              ),
              const SizedBox(height: 10),
              ValueListenableBuilder<bool>(
                valueListenable: formViewModel.canLogin,
                child: const Text('Log In'),
                builder: (context, canLogin, child) {
                  return ElevatedButton(
                    onPressed: canLogin ? () {} : null,
                    child: child,
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }

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

更多关于Flutter响应式计算值管理插件computed_value_notifier的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter响应式计算值管理插件computed_value_notifier的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


computed_value_notifier 是一个用于 Flutter 的插件,它允许你创建响应式的计算值。它的核心思想是基于其他 ValueNotifier 的值来计算一个新的值,并在依赖的值发生变化时自动更新这个计算值。

安装

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

dependencies:
  flutter:
    sdk: flutter
  computed_value_notifier: ^1.0.0

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

基本用法

  1. 创建一个 ComputedValueNotifier

    ComputedValueNotifier 需要一个计算函数,这个函数会基于其他 ValueNotifier 的值来计算一个新的值。

    import 'package:flutter/material.dart';
    import 'package:computed_value_notifier/computed_value_notifier.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      [@override](/user/override)
      Widget build(BuildContext context) {
        return MaterialApp(
          home: HomeScreen(),
        );
      }
    }
    
    class HomeScreen extends StatefulWidget {
      [@override](/user/override)
      _HomeScreenState createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
      final ValueNotifier<int> counter1 = ValueNotifier(0);
      final ValueNotifier<int> counter2 = ValueNotifier(0);
    
      late final ComputedValueNotifier<int> sum;
    
      [@override](/user/override)
      void initState() {
        super.initState();
        sum = ComputedValueNotifier(
          () => counter1.value + counter2.value,
          [counter1, counter2],
        );
      }
    
      [@override](/user/override)
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('ComputedValueNotifier Example'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ValueListenableBuilder<int>(
                  valueListenable: counter1,
                  builder: (context, value, child) {
                    return Text('Counter 1: $value');
                  },
                ),
                ValueListenableBuilder<int>(
                  valueListenable: counter2,
                  builder: (context, value, child) {
                    return Text('Counter 2: $value');
                  },
                ),
                ValueListenableBuilder<int>(
                  valueListenable: sum,
                  builder: (context, value, child) {
                    return Text('Sum: $value');
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              FloatingActionButton(
                onPressed: () => counter1.value++,
                child: Icon(Icons.add),
              ),
              SizedBox(width: 10),
              FloatingActionButton(
                onPressed: () => counter2.value++,
                child: Icon(Icons.add),
              ),
            ],
          ),
        );
      }
    
      [@override](/user/override)
      void dispose() {
        counter1.dispose();
        counter2.dispose();
        sum.dispose();
        super.dispose();
      }
    }
    
  2. 解释代码

    • counter1counter2 是两个 ValueNotifier,它们分别存储两个计数器的值。
    • sum 是一个 ComputedValueNotifier,它基于 counter1counter2 的值来计算它们的和。
    • counter1counter2 的值发生变化时,sum 会自动重新计算并通知其监听器。
    • 使用 ValueListenableBuilder 来监听 counter1counter2sum 的变化,并在 UI 中显示它们的值。
  3. 注意事项

    • ComputedValueNotifier 会自动监听传入的 ValueNotifier 列表中的值变化。当这些值发生变化时,它会重新执行计算函数并更新自身的值。
    • 你需要在 dispose 方法中手动释放 ComputedValueNotifier 和它所依赖的 ValueNotifier

高级用法

你可以在计算函数中执行更复杂的逻辑,例如条件判断、循环等。ComputedValueNotifier 会自动处理依赖关系,并在依赖的值发生变化时重新计算。

final ValueNotifier<bool> isLoggedIn = ValueNotifier(false);
final ValueNotifier<String> username = ValueNotifier('');

late final ComputedValueNotifier<String> greeting;

[@override](/user/override)
void initState() {
  super.initState();
  greeting = ComputedValueNotifier(
    () => isLoggedIn.value ? 'Hello, ${username.value}!' : 'Please log in',
    [isLoggedIn, username],
  );
}
回到顶部