Flutter 阻塞侦听器未侦听状态变化

k75qkfdt  于 2023-02-05  发布在  Flutter
关注(0)|答案(3)|浏览(189)

我正在使用flutter_bloc库创建一个验证码页面。下面是我尝试做的。

class PhonePage extends StatelessWidget {
  static Route route() {
    return MaterialPageRoute<void>(builder: (_) => PhonePage());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider(
        create: (_) =>
            ValidationCubit(context.repository<AuthenticationRepository>()),
        child: PhoneForm(),
      ),
    );
  }
}

class PhoneForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocConsumer<ValidationCubit, ValidationState>(
      listener: (context, state) {
        print('Listener has been called');
        if (state.status.isSubmissionFailure) {
          _showVerificationError(context);
        } else if (state.status.isSubmissionSuccess) {
          _showVerificationSuccess(context);
        }
      },
      builder: (context, state) {
        return Container(
          child: SingleChildScrollView(
            child: Padding(
              padding: EdgeInsets.all(16.0),
              child: Column(
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  _HeaderAndTitle(),
                  _VerificationInput(),
                  _VerifyButton()
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  void _showVerificationError(context) {
    Scaffold.of(context)
      ..hideCurrentSnackBar()
      ..showSnackBar(const SnackBar(content: Text('Validation error')));
  }

  void _showVerificationSuccess(context) {
    Scaffold.of(context)
      ..hideCurrentSnackBar()
      ..showSnackBar(const SnackBar(
        content: Text('Validation Success'),
        backgroundColor: Colors.green,
      ));
  }
}

...

class _VerifyButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<ValidationCubit, ValidationState>(
        builder: (context, state) {
      return RaisedButton.icon(
          color: Colors.blue,
          padding: EdgeInsets.symmetric(horizontal: 38.0, vertical: 12.0),
          textColor: Colors.white,
          icon: state.status.isSubmissionInProgress
              ? Icon(FontAwesomeIcons.ellipsisH)
              : Icon(null),
          label: Text(state.status.isSubmissionInProgress ? '' : 'Verify',
              style: TextStyle(fontSize: 16.0)),
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
          onPressed: state.status.isValid
              ? () => context.bloc<ValidationCubit>().verifyCode()
              : null);
    });
  }
}

现在verifyCode()函数是一个在ValidationCubit内部定义的异步函数。它发出状态设置为loading、success和failure的状态。但是侦听器没有接收到这些更改并显示snackbar。我不知道为什么?我也使用了flutter_bloc文档中建议的Formz库。下面是verifyCode部分。

Future<void> verifyCode() async {
    if (!state.status.isValidated) return;
    emit(state.copyWith(status: FormzStatus.submissionInProgress));
    try {
      // send validation code to server here
      await _authenticationRepository.loginWithEmailAndPassword(
          email: 'email@email.com', password: '12');
      emit(state.copyWith(status: FormzStatus.submissionSuccess));
    } on Exception {
      emit(state.copyWith(status: FormzStatus.submissionFailure));
    }
  }

验证码模型如下所示:

class ValidationState extends Equatable {
  final VerificationCode verificationCode;
  final FormzStatus status;

  const ValidationState({this.verificationCode, this.status});

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

  ValidationState copyWith(
      {VerificationCode verificationCode, FormzStatus status}) {
    return ValidationState(
        verificationCode: verificationCode ?? this.verificationCode,
        status: status ?? this.status);
  }
}

验证状态类为:

class ValidationState extends Equatable {
  final VerificationCode verificationCode;
  final FormzStatus status;

  const ValidationState({this.verificationCode, this.status});

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

  ValidationState copyWith(
      {VerificationCode verificationCode, FormzStatus status}) {
    return ValidationState(
        verificationCode: verificationCode ?? this.verificationCode,
        status: status ?? this.status);
  }
}
ibps3vxo

ibps3vxo1#

我觉得问题出在你的国家级。
与BlocBuilder中的builder不同,每个状态更改(不包括初始状态)只调用一次listener,它是一个void函数。
每当肘节发出一个新的状态时,它就会与前一个状态进行比较,如果它们是“不同的”,监听器功能就会被触发。
在您的情况下,您使用Equatable,其中verificationCodeprops,这意味着当比较两个状态时,仅测试verificationCode。这样,BLoC使用者认为两个状态相等,并且不会再次触发侦听器函数。
如果检查verifyCode()函数,唯一更改的参数是status
为了解决这个问题,请将status属性添加到state类的props列表中。

@override
  List<Object> get props => [this.verificationCode, this.status];
fjaof16o

fjaof16o2#

如果您想更新相同的状态,只需在调用您的更新状态之前添加一个状态,如下所示。如果您想再次更新“已加载"状态,请在此之前调用”正在加载“状态,然后调用”已加载“状态,以便BlocListener和BlocBuilder将侦听它

已编辑我已将使用块更改为cubit,cubit可以连续发出相同的状态,并且bloclistener和blocbuilder可以侦听它

ulydmbyx

ulydmbyx3#

我需要从列表中删除一个列表项,应用程序应该在删除前弹出一个弹出窗口。不知何故,你拒绝删除弹出窗口,通过没有按钮或点击弹出窗口之外,最后一个状态不会改变。之后,如果你想删除同一个项目,它不是触发器,因为所有参数都与以前的状态相同,equatable说它是相同的。要摆脱这个问题,你需要定义一个rand函数,并把它放在你的emit状态之前。2你需要给你的状态添加一个新的参数,并且你需要添加一些 prop 。3它的工作原理就像一个符咒。
我的州;

class SomeDeleteOnPressedState extends SomeState
    with EquatableMixin {
  final int index;
  final List<Result> result;
  final String currentLocation;
  final int rand;/// this is the unique part.

  SomeDeleteOnPressedState({
    required this.index,
    required this.result,
    required this.currentLocation,
    required this.rand,
  });
// don't forget to add rand parameter in props. it will make the difference here.
  @override
  List<Object> get props => <Object>[index, result, currentLocation, rand];
}

和我的集团;

on<SomeDeleteEvent>((event,emit){
int rand =Random().nextInt(100000);
 emit(
            SomeDeleteOnPressedState(
              currentLocation: event.currentLocation,
              index: event.index,
              result: event.result,
              rand: rand,/// every time it will send a different rand, so this state is always will be different.
            ),
          );

});

希望有帮助。

相关问题