Flutter字段代理插件field_delegate的使用

Flutter字段代理插件field_delegate的使用

Field 类是一个抽象的可变字段代理,可以用作访问不同数据源的接口。

请参阅在 shared_preferences_field_delegate 中的示例用法。

使用

Field 类包含值的获取器、设置器和一个变化流。

Field<int> intField;
int value = intField.get(); // 获取字段的当前值
Future<void> result = intField.set(1); // 设置字段的新值
Stream<int> changes = intField.onChanged; // 监听字段的变化

你可以使用 Field.map 方法将 Field 的值映射到另一种类型。

Field<int> intField;
Field<String> mappedField = Field.map<int, String>(
  source: intField, // 源字段
  mapToSource: (value) => int.parse(value), // 将字符串转换为整数
  mapFromSource: (value) => value.toString(), // 将整数转换为字符串
);

如果你有一个可空的 Field,可以使用默认值将其映射为不可空的 Field。使用 Field.notNullable 函数来实现这一点。

Field<int?> intNullableField;
Field<int> intNotNullableField = Field.notNullable(
  source: intNullableField, // 可空字段
  defaultValue: 0, // 默认值
);

完整示例Demo

以下是一个完整的示例,展示了如何使用 Field 类及其相关方法。

import 'dart:async';

// 假设 Field 是一个已经定义好的类
class Field<T> {
  T _value;

  Field(this._value);

  T get() => _value;

  Future<void> set(T newValue) async {
    _value = newValue;
    onChanged.add(newValue);
  }

  StreamController<T> onChanged = StreamController<T>.broadcast();

  Stream<T> get stream => onChanged.stream;
}

void main() {
  // 创建一个整数字段
  Field<int> intField = Field<int>(0);

  // 获取字段的初始值
  int value = intField.get();
  print('Initial value: $value');

  // 设置新值并监听变化
  intField.set(1).then((_) {
    print('New value: ${intField.get()}');
  });

  // 监听字段的变化
  intField.stream.listen((newValue) {
    print('Value changed to: $newValue');
  });

  // 映射字段到另一种类型
  Field<String> mappedField = Field.map<int, String>(
    source: intField,
    mapToSource: (value) => int.parse(value),
    mapFromSource: (value) => value.toString(),
  );

  // 获取映射字段的值
  String mappedValue = mappedField.get();
  print('Mapped value: $mappedValue');

  // 设置映射字段的新值
  mappedField.set("2").then((_) {
    print('Mapped new value: ${mappedField.get()}');
  });

  // 处理可空字段
  Field<int?> intNullableField = Field<int?>(null);
  Field<int> intNotNullableField = Field.notNullable(
    source: intNullableField,
    defaultValue: 0,
  );

  // 获取不可空字段的值
  int notNullableValue = intNotNullableField.get();
  print('Not nullable value: $notNullableValue');

  // 设置不可空字段的新值
  intNotNullableField.set(3).then((_) {
    print('Not nullable new value: ${intNotNullableField.get()}');
  });
}

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

1 回复

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


field_delegate 是一个 Flutter 插件,用于简化表单字段的管理和验证。它通过代理模式将字段的状态管理和验证逻辑与 UI 分离,使得代码更加简洁和易于维护。

安装

首先,在 pubspec.yaml 文件中添加 field_delegate 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  field_delegate: ^1.0.0  # 请检查最新版本

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

基本用法

  1. 创建字段代理

    使用 FieldDelegate 来创建字段代理。你可以为每个表单字段创建一个代理,并指定验证规则。

    import 'package:field_delegate/field_delegate.dart';
    
    final emailField = FieldDelegate<String>(
      validator: (value) {
        if (value == null || value.isEmpty) {
          return 'Email is required';
        }
        if (!value.contains('@')) {
          return 'Invalid email format';
        }
        return null;
      },
    );
    
    final passwordField = FieldDelegate<String>(
      validator: (value) {
        if (value == null || value.isEmpty) {
          return 'Password is required';
        }
        if (value.length < 6) {
          return 'Password must be at least 6 characters';
        }
        return null;
      },
    );
    
  2. 在 UI 中使用字段代理

    TextField 中使用 FieldDelegate 来管理字段的状态和验证。

    import 'package:flutter/material.dart';
    
    class LoginForm extends StatelessWidget {
      final emailField = FieldDelegate<String>(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Email is required';
          }
          if (!value.contains('@')) {
            return 'Invalid email format';
          }
          return null;
        },
      );
    
      final passwordField = FieldDelegate<String>(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Password is required';
          }
          if (value.length < 6) {
            return 'Password must be at least 6 characters';
          }
          return null;
        },
      );
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Login'),
          ),
          body: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              children: [
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Email',
                    errorText: emailField.error,
                  ),
                  onChanged: emailField.update,
                ),
                SizedBox(height: 16),
                TextField(
                  obscureText: true,
                  decoration: InputDecoration(
                    labelText: 'Password',
                    errorText: passwordField.error,
                  ),
                  onChanged: passwordField.update,
                ),
                SizedBox(height: 16),
                ElevatedButton(
                  onPressed: () {
                    if (emailField.validate() && passwordField.validate()) {
                      // 表单验证通过,执行登录逻辑
                      print('Email: ${emailField.value}');
                      print('Password: ${passwordField.value}');
                    }
                  },
                  child: Text('Login'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
  3. 验证表单

    在按钮的 onPressed 回调中,调用 validate() 方法来验证字段。如果所有字段都通过验证,则可以继续执行后续逻辑。

高级用法

  1. 自定义验证规则

    你可以在 validator 中定义复杂的验证逻辑,甚至可以结合正则表达式进行验证。

  2. 监听字段变化

    FieldDelegate 提供了 addListener 方法,可以监听字段值的变化。

    emailField.addListener(() {
      print('Email changed: ${emailField.value}');
    });
    
  3. 重置字段

    你可以使用 reset() 方法来重置字段的值和错误状态。

    emailField.reset();
    passwordField.reset();
回到顶部