FlutterBLoC:如何用空值更新状态?

vdgimpew  于 2023-04-22  发布在  Flutter
关注(0)|答案(3)|浏览(115)

当你在BLoC中更新一个状态时,你如何处理“接受的空值”?我使用flutter_bloc包。
我有一个表单,其中的数值变量是可以为空的,这样我就可以在提交表单之前检查它们的有效性。但是当我发出一个新的状态时,我使用state.copyWith(var 1?,var 2?)...所以当使用null值来更新参数时,该值不会更新。
面对我为每个字段使用自定义FieldStatus枚举。在我的表单提交中,我可以检查每个字段的状态。但这有点冗长...并且它需要为每个字段使用2个值而不是1个值,这不是很令人满意。
我还可以根据FieldStatus的新值强制该值为null,但这有点棘手,不太令人满意。
你会如何处理这样的情况?
我是这么做的:
国家:

part of 'phhfgroup_bloc.dart';

class PhhfGroupState extends Equatable
{
    final double? height;
    final FieldStatus heightStatus;
    
    const PhhfGroupState({this.height, this.heightStatus = FieldStatus.initial});
    
    @override
    List<Object?> get props => [height, heightStatus];
    
    PhhfGroupState copyWith({double? height, FieldStatus? heightStatus})
    {
        return PhhfGroupState(
            height: height ?? this.height,
            heightStatus: heightStatus ?? this.heightStatus
        );
    }
}

活动:

part of 'phhfgroup_bloc.dart';

abstract class PhhfGroupEvent extends Equatable
{
    const PhhfGroupEvent();
    
    @override
    List<Object> get props => [];
}

class HeightChanged extends PhhfGroupEvent
{
    const HeightChanged({required this.height});
    final String height;

    @override
    List<Object> get props => [height];
}

经办人:

import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:myapp/models/statuses.dart';

part 'phhfgroup_event.dart';
part 'phhfgroup_state.dart';

class PhhfGroupBloc extends Bloc<PhhfGroupEvent, PhhfGroupState>
{
    PhhfGroupBloc() : super()
    {
        on<HeightChanged>(_mapHeightEventToState);
    }
    
    void _mapHeightEventToState(HeightChanged event, Emitter<PhhfGroupState> emit)
    {
        if(event.height.isEmpty)
        {
            emit(this.state.copyWith(
                height: null,
                heightStatus: FieldStatus.empty
            ));
        }
        
        else
        {
            double? height = double.tryParse(event.height);
            
            if(height == null)
                emit(this.state.copyWith(
                    height: null,
                    heightStatus: FieldStatus.nonnumeric
                ));
            
            else emit(this.state.copyWith(
                height: height,
                heightStatus: FieldStatus.numeric
            ));
        }
    }
}

谢谢!

nbnkbykc

nbnkbykc1#

通过使用freeze,您可以执行以下操作:

void main() {
  var person = Person('Remi', 24);

  // `age` not passed, its value is preserved
  print(person.copyWith(name: 'Dash')); // Person(name: Dash, age: 24)
  // `age` is set to `null`
  print(person.copyWith(age: null)); // Person(name: Remi, age: null)
}

如果你不想使用另一个包,我建议添加一个参数来控制可空值。

class PhhfGroupState extends Equatable
{
    final double? height;
    final FieldStatus heightStatus;
    
    const PhhfGroupState({this.height, this.heightStatus = FieldStatus.initial});
    
    @override
    List<Object?> get props => [height, heightStatus];
    
    PhhfGroupState copyWith({double? height, FieldStatus? heightStatus, bool clearHeight = false})
    {
        return PhhfGroupState(
            height: clearHeight == true ? null : height ?? this.height,
            heightStatus: heightStatus ?? this.heightStatus
        );
    }
}

如果你有一堆nullable字段,我强烈推荐freeze,但对于其他字段,只需为它添加一个标志。

wsxa1bj1

wsxa1bj12#

另一种方法是使用**ValueGetter**。
例如,下面的password

@immutable
class LoginPageState {
  const LoginPageState({
    this.phone,
    this.password,
  });

  final String? phone;
  final String? password;

  LoginPageState copyWith({
    String? phone,
    ValueGetter<String?>? password,
  }) {
    return LoginPageState(
      phone: phone ?? this.phone,
      password: password != null ? password() : this.password,
    );
  }
}

password设置为null

void resetPassword() {
  final newState = state.copyWith(password: () => null);
  emit(newState);
}

你不需要任何额外的旗帜或 Package 。

tzxcd3kk

tzxcd3kk3#

非常感谢,因为这正是我所需要的!避免大量的样板代码来实现这个简单的目标...
为了实现我所需要的,我将用途:

  • 冻结以帮助管理状态/事件
  • 我的FieldStatus枚举,使某些信息在视图中可用

相关问题