gpt4 book ai didi

flutter - 如何在Flutter中使用Bloc模式处理用户注册错误

转载 作者:行者123 更新时间:2023-12-03 08:44:19 25 4
gpt4 key购买 nike

  • 这是我尝试过的一些代码。在这段代码中,我使用了bloc。但我想在此注册页面中进行错误处理。
  • 如果注册成功,则为
  • ,然后只有OTP对话框需要打开
  • 当用户注册失败时,用户将获得适当的消息。
  • 如果正在注册,则应指示加载。
  • 成功注册后的
  • 。它会显示一个OTP。输入otp后,它将重定向另一个“警告对话框”。希望您理解这个问题,请帮助我。我也在这段代码中尝试了很多次错误处理,但是您发现了错误处理,但这是不合适的。我希望你能帮助我。您很少的帮助就能使我过得愉快。

  • 这是完整的源代码 https://github.com/rutvikgumasana/signup/tree/master


    import 'package:flutter/gestures.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_form_builder/flutter_form_builder.dart';
    import 'package:flutter_masked_text/flutter_masked_text.dart';

    import 'package:font_awesome_flutter/font_awesome_flutter.dart';
    import 'package:passcode/passcode.dart';
    import 'package:pin_code_fields/pin_code_fields.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:tudo/src/modules/signup/_models/countries.dart';
    import 'package:tudo/src/modules/signup/index.dart';
    import 'package:tudo/src/styles/colors.dart';

    import 'package:tudo/src/utils/app_constants_value.dart';
    import 'package:tudo/src/utils/navigation_helper.dart';
    import 'package:tudo/src/utils/roundrectbutton.dart';
    import 'package:tudo/src/utils/validator.dart';
    import 'package:tudo/src/widgets/loader.dart';

    import 'package:tudo/src/widgets/toast.dart';
    import 'dart:math' as math;

    class SignupScreen extends StatefulWidget {
    const SignupScreen({
    Key key,
    @required SignupBloc signupBloc,
    }) : _signupBloc = signupBloc,
    super(key: key);

    final SignupBloc _signupBloc;

    @override
    SignupScreenState createState() {
    return new SignupScreenState(_signupBloc);
    }
    }

    class SignupScreenState extends State<SignupScreen>
    with TickerProviderStateMixin {
    String submittedString = "";
    final changeNotifier = StreamController<Functions>.broadcast();

    final SignupBloc _signupBloc;
    SignupScreenState(this._signupBloc);
    final formKey = new GlobalKey<FormState>();
    bool _validate = false;
    List<Country> _countries = [];
    bool _isError = false;
    bool _isLoading = false;
    bool _obscureText = true;
    Person person = new Person();
    var controller = new MaskedTextController(mask: '(000)-000-0000');

    String passcode;
    final _emailFocusNode = new FocusNode();
    final _passwordFocusNode = new FocusNode();
    final _fnameFocuNode = new FocusNode();
    final _lnameFocusNode = new FocusNode();
    final TextEditingController _email = new TextEditingController();
    final TextEditingController _add = new TextEditingController();
    final TextEditingController _fn = new TextEditingController();
    final TextEditingController _ln = new TextEditingController();
    final TextEditingController _pho = new TextEditingController();
    final TextEditingController _pass = new TextEditingController();

    TextEditingController phoneController = new TextEditingController();

    static List<CountryModel> _dropdownItems = new List();

    String otpWaitTimeLabel = "";

    CountryModel _dropdownValue;
    TextEditingController otpcontroller = TextEditingController();
    String thisText = "";
    int pinLength = 6;

    bool hasError = false;
    bool showAlertBox = false;
    String errorMessage;

    SharedPreferences prefs;
    DateTime target;
    String timeLeft = "";
    bool running = true;

    @override
    void initState() {
    super.initState();

    this._signupBloc.dispatch(LoadSignupEvent());
    }

    @override
    void dispose() {
    prefs.setInt('target', target.millisecondsSinceEpoch);
    running = false;
    super.dispose();
    }

    void _toggle() {
    setState(() {
    _obscureText = !_obscureText;
    });
    }

    Widget _buildLogo() {
    return new Image(
    image: new AssetImage("assets/logo.png"),
    height: 150,
    width: 150,
    );
    }

    Widget _buildEmailField() {
    return TextFormField(
    controller: _email,
    focusNode: _emailFocusNode,
    decoration: new InputDecoration(
    prefixIcon: Icon(
    Icons.email,
    ),
    labelText: AppConstantsValue.appConst['signup']['email']['translation'],
    border: UnderlineInputBorder(),
    filled: false,
    hintText: 'Your email address',
    ),
    keyboardType: TextInputType.emailAddress,
    validator: Validators().validateEmail,
    onSaved: (String value) {
    person.email = value;
    },
    );
    }

    Widget _buildCountry(List<Country> countries) {
    if (countries.length > 0 && _dropdownItems.length != countries.length - 1) {
    print("countries list");
    print(countries[0].name);
    for (int i = 0; i < countries.length; i++) {
    if (countries[i].name.toLowerCase() != 'world') {
    _dropdownItems.add(
    CountryModel(
    country: countries[i].name, countryCode: countries[i].isdCode),
    );
    }
    }
    }
    return FormBuilder(
    autovalidate: true,
    initialValue: {},
    child: FormBuilderCustomField(
    attribute: "Country",
    validators: [
    FormBuilderValidators.required(),
    ],
    formField: FormField(
    builder: (FormFieldState<dynamic> field) {
    return DropdownButtonHideUnderline(
    child: new Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[
    new InputDecorator(
    decoration: InputDecoration(
    filled: false,
    hintText: 'Choose Country',
    prefixIcon: Icon(Icons.location_on),
    labelText: _dropdownValue == null
    ? 'Where are you from'
    : 'From',
    errorText: field.errorText,
    ),
    isEmpty: _dropdownValue == null,
    child: new DropdownButton<CountryModel>(
    value: _dropdownValue,
    isDense: true,
    onChanged: (CountryModel newValue) {
    print('value change');
    print(newValue);
    person.country = newValue.country;
    person.countryCode = newValue.countryCode;
    setState(() {
    _dropdownValue = newValue;
    phoneController.text = _dropdownValue.countryCode;
    field.didChange(newValue);
    });
    },
    items: _dropdownItems.map(
    (CountryModel value) {
    return DropdownMenuItem<CountryModel>(
    value: value,
    child: Text(value.country),
    );
    },
    ).toList(),
    ),
    ),
    ],
    ),
    );
    },
    ),
    ),
    );
    }

    Widget _buildPhonefiled() {
    return Row(
    children: <Widget>[
    new Expanded(
    child: new TextFormField(
    controller: phoneController,
    enabled: false,
    decoration: InputDecoration(
    filled: false,
    prefixIcon: Icon(FontAwesomeIcons.globe),
    labelText: 'code',
    hintText: "Country code",
    ),
    ),
    flex: 2,
    ),
    new SizedBox(
    width: 10.0,
    ),
    new Expanded(
    child: new TextFormField(
    controller: controller,
    keyboardType: TextInputType.number,
    validator: Validators().validateMobile,
    decoration: InputDecoration(
    filled: false,
    labelText: 'mobile',
    hintText: "Mobile number",
    prefixIcon: new Icon(Icons.mobile_screen_share),
    ),
    onSaved: (String value) {
    person.phoneNumber = value;
    },
    ),
    flex: 5,
    ),
    ],
    );
    }

    Widget _buildFnamefiled() {
    return TextFormField(
    controller: _fn,
    focusNode: _fnameFocuNode,
    decoration: new InputDecoration(
    filled: false,
    hintText: 'Enter your First name',
    prefixIcon: Icon(
    Icons.account_circle,
    // size: 28.0,
    ),
    labelText: AppConstantsValue.appConst['signup']['firstname']
    ['translation']),
    keyboardType: TextInputType.text,
    validator: Validators().validateName,
    onSaved: (String value) {
    person.firstname = value;
    },
    );
    }

    Widget _buildLnamefiled() {
    return TextFormField(
    validator: Validators().validateName,
    controller: _ln,
    focusNode: _lnameFocusNode,
    decoration: new InputDecoration(
    filled: false,
    hintText: 'Enter your Last name',
    prefixIcon: Icon(
    Icons.account_circle,
    // size: 28.0,
    ),
    labelText: AppConstantsValue.appConst['signup']['lastname']
    ['translation']),
    keyboardType: TextInputType.text,
    onSaved: (String value) {
    person.lastname = value;
    },
    );
    }

    Widget _buildPasswordfiled() {
    return TextFormField(
    validator: Validators().validatePassword,
    obscureText: _obscureText,
    controller: _pass,
    focusNode: _passwordFocusNode,
    decoration: new InputDecoration(
    filled: false,
    hintText: 'Enter your password',
    prefixIcon: Icon(
    Icons.vpn_key,
    ),
    suffixIcon: GestureDetector(
    dragStartBehavior: DragStartBehavior.down,
    onTap: _toggle,
    child: Icon(
    _obscureText ? Icons.visibility : Icons.visibility_off,
    semanticLabel: _obscureText
    ? AppConstantsValue.appConst['login']['show_password']
    ['translation']
    : AppConstantsValue.appConst['login']['hide_password']
    ['translation'],
    ),
    ),
    labelText: AppConstantsValue.appConst['signup']['password']
    ['translation'],
    ),
    onSaved: (String value) {
    person.password = value;
    },
    );
    }

    Widget _buildTermsAndContionsCheck() {
    return FormField(
    builder: (FormFieldState state) {
    return Row(
    mainAxisAlignment: MainAxisAlignment.start,
    children: <Widget>[
    Checkbox(
    value: person.termsAndCondition,
    onChanged: (bool value) {
    setState(() {
    person.termsAndCondition = value;
    });
    },
    ),
    Text(
    AppConstantsValue.appConst['signup']['termsandcondition']
    ['translation'],
    ),
    ],
    );
    },
    );
    }

    _onAlertotp() {
    return showDialog<void>(
    context: context,
    barrierDismissible: false, // user must tap button!
    builder: (BuildContext context) {
    return AlertDialog(
    title: Text('Enter OTP'),
    content: SingleChildScrollView(
    child: ListBody(
    children: <Widget>[
    Container(
    height: MediaQuery.of(context).size.height / 2.4,
    width: MediaQuery.of(context).size.width,
    alignment: Alignment.center,
    child: ListView(
    children: <Widget>[
    Padding(
    padding: const EdgeInsets.symmetric(vertical: 8.0),
    child: Text(
    'We have Texted and/or Emailed OTP (One Time Pin) to your registered cell phone and/ or email account. Please check and enter OTP below to activate your TUDO account.',
    style: TextStyle(
    fontWeight: FontWeight.bold, fontSize: 15),
    textAlign: TextAlign.center,
    ),
    ),
    Center(
    child: Text(
    "timerString",
    style: TextStyle(fontSize: 25),
    ),
    ),
    Padding(
    padding: const EdgeInsets.symmetric(
    vertical: 8.0, horizontal: 30),
    child: PinCodeTextField(
    length: 6, // must be greater than 0
    obsecureText: false, //optional, default is false
    shape: PinCodeFieldShape
    .underline, //optional, default is underline
    onDone: (String value) {
    setState(() {
    passcode = value;
    print(value);
    });
    },

    textStyle: TextStyle(
    fontWeight: FontWeight
    .bold), //optinal, default is TextStyle(fontSize: 18, color: Colors.black, fontWeight: FontWeight.bold)
    onErrorCheck: (bool value) {
    setState(() {
    hasError = value;
    });
    },
    shouldTriggerFucntions:
    changeNotifier.stream.asBroadcastStream(),
    ),
    ),
    Padding(
    padding: const EdgeInsets.symmetric(horizontal: 30.0),
    child: Text(
    hasError
    ? "*Please fill up all the cells and press VERIFY again"
    : "",
    style: TextStyle(
    color: Colors.red.shade300, fontSize: 12),
    ),
    ),
    SizedBox(
    height: 5,
    ),
    RichText(
    textAlign: TextAlign.center,
    text: TextSpan(
    text: "Didn't receive the code? ",
    style:
    TextStyle(color: Colors.black54, fontSize: 15),
    children: [
    TextSpan(
    text: " RESEND",
    // recognizer: onTapRecognizer,
    style: TextStyle(
    color: colorStyles["primary"],
    fontWeight: FontWeight.bold,
    fontSize: 16))
    ]),
    ),
    SizedBox(
    height: 7,
    ),
    Container(
    margin: const EdgeInsets.symmetric(
    vertical: 16.0, horizontal: 30),
    child: ButtonTheme(
    height: 50,
    child: FlatButton(
    onPressed: () async {
    _onAlertrunnigbusiness(context);
    },
    child: Center(
    child: Text(
    "VERIFY".toUpperCase(),
    style: TextStyle(
    color: Colors.white,
    fontSize: 18,
    fontWeight: FontWeight.bold),
    )),
    ),
    ),
    decoration: BoxDecoration(
    color: colorStyles["primary"],
    borderRadius: BorderRadius.circular(5),
    ),
    ),
    ],
    ),
    ),
    ],
    ),
    ),
    actions: <Widget>[
    FlatButton(
    child: Text('Close'),
    onPressed: () {
    Navigator.of(context).pop();
    },
    ),
    ],
    );
    },
    );
    }

    _onAlertrunnigbusiness(context) {
    return showDialog<void>(
    context: context,
    barrierDismissible: false, // user must tap button!
    builder: (BuildContext context) {
    return AlertDialog(
    title: Text('Are you running Business?'),
    content: Container(
    child: Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    SizedBox(
    height: 10,
    ),
    Text(
    "TUDO.App aims at Businesses bridging gaps between Business Service Providers and Consumers collaborate on unique technology platform. If you own a business, we strongly recommend, provide your business information to grow your customer base and expand your business services. Any questions? Call us @1-800-888-TUDO"),
    SizedBox(
    height: 10,
    ),
    Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: <Widget>[
    FlatButton.icon(
    icon: Icon(FontAwesomeIcons.arrowCircleRight),
    label: Text('No'),
    color: colorStyles["primary"],
    textColor: Colors.white,
    padding:
    EdgeInsets.symmetric(vertical: 10, horizontal: 15),
    shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(7),
    ),
    onPressed: () {
    NavigationHelper.navigatetoMainscreen(context);
    },
    ),
    SizedBox(height: 10),
    FlatButton.icon(
    icon: Icon(FontAwesomeIcons.arrowCircleRight),
    label: Text('Yes'),
    color: colorStyles["primary"],
    textColor: Colors.white,
    padding:
    EdgeInsets.symmetric(vertical: 10, horizontal: 15),
    shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(7),
    ),
    onPressed: () {
    NavigationHelper.navigatetoBspsignupcreen(context);
    },
    ),
    ],
    )
    ],
    ),
    ),
    actions: <Widget>[
    FlatButton(
    child: Text('Close'),
    onPressed: () {
    Navigator.of(context).pop();
    },
    ),
    ],
    );
    },
    );
    }

    Widget _buildClearButton() {
    return new FlatButton(
    onPressed: () {
    _email.clear();
    _fn.clear();
    _ln.clear();
    _pho.clear();
    _add.clear();
    _pass.clear();
    _isError = false;

    setState(() {
    _isError = false;
    });
    },
    child: Text(
    AppConstantsValue.appConst['signup']['clear']['translation'],
    style: TextStyle(letterSpacing: 1.5),
    ),
    );
    }


    Widget _buildSignupButton(SignupBloc signupBloc, BuildContext context) {
    return GestureDetector(
    child: RoundrectButton.buildRoundedRectButton(
    AppConstantsValue.appConst['signup']['signup']['translation'],
    signUpGradients,
    false),
    onTap: () {
    // _submit();
    final FormState form = formKey.currentState;
    form.save();
    if (form.validate() && person.termsAndCondition) {
    setState(() {
    _isLoading = true;
    });
    Map<String, dynamic> signupdata = {
    'email': person.email,
    'country': person.country,
    'countyCode': person.countryCode,
    'phoneNumber': person.phoneNumber,
    'firstName': person.firstname,
    'lastName': person.lastname,
    'password': person.password,
    };
    _isError
    ? new Container(child: Text("Error"))
    : widget._signupBloc.dispatch(
    SignupButtonClickedEvent(signupdata: signupdata),
    );
    } else {
    print("Toast is printed");
    Errortoast().showColoredToast();
    setState(() {
    _isLoading = false;
    _validate = true;
    });
    }
    },
    );
    }

    Widget _buildBackButton(BuildContext context) {
    return FlatButton(
    child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
    Icon(Icons.arrow_back_ios),
    Text(AppConstantsValue.appConst['signup']['backtologin']
    ['translation'])
    ],
    ),
    onPressed: () => Navigator.pop(context, false),
    );
    }

    Widget _buildLoader() {
    return Loader(
    color: colorStyles["primary"],
    );
    }

    Widget content(signupBloc, context, List<Country> countries) {
    return SafeArea(
    top: false,
    bottom: false,
    child: Form(
    key: formKey,
    autovalidate: _validate,
    child: Scrollbar(
    child: SingleChildScrollView(
    dragStartBehavior: DragStartBehavior.down,
    padding: const EdgeInsets.symmetric(horizontal: 16.0),
    child: new Container(
    margin: EdgeInsets.fromLTRB(30, 0, 30, 0),
    child: new Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
    _buildLogo(),
    _buildEmailField(),
    _buildCountry(countries),
    _buildPhonefiled(),
    _buildFnamefiled(),
    _buildLnamefiled(),
    _buildPasswordfiled(),
    _buildTermsAndContionsCheck(),
    SizedBox(),
    _isError ? new Text('Fail to signup') : SizedBox(),
    _isLoading ? _buildLoader() : SizedBox(),
    _buildClearButton(),
    _buildSignupButton(signupBloc, context),
    _buildBackButton(context),
    ],
    ),
    ),
    ),
    ),
    ),
    );
    }

    @override
    Widget build(BuildContext context) {
    return BlocBuilder<SignupBloc, SignupState>(
    bloc: widget._signupBloc,
    builder: (
    BuildContext context,
    SignupState currentState,
    ) {
    if (currentState is UnSignupState) {
    return Container(
    height: MediaQuery.of(context).size.height / 1.10,
    width: MediaQuery.of(context).size.width / 1.10,
    child: Center(
    child: _buildLoader(),
    ),
    );
    }

    if (currentState is ErrorSignupState) {
    _isLoading = false;
    _isError = true;
    showAlertBox = false;
    return Container(
    child: content(_signupBloc, context, _countries),
    );
    }
    if (currentState is InSignupState) {
    _countries = currentState.countries.countries;
    return Container(child: content(_signupBloc, context, _countries));
    }

    if (currentState is SignupButtonClickedEvent) {
    print('SignupButtonClickedEvent clicked');
    return Container();
    }

    if (currentState is SignupSuccessState) {
    print(
    ' You are awesome. you have successfully registered without confirmation');
    print(currentState.signupUser.toJson());
    print("Hey Otp Is opned");
    WidgetsBinding.instance.addPostFrameCallback((_) {
    // _never();

    _onAlertotp();
    });
    _isLoading = false;
    showAlertBox = true;
    return Container(
    child: content(_signupBloc, context, _countries),
    );
    }

    if (currentState is SignupVerficationOtp) {
    print('signup verficitaion otp button clicked');
    return Container();
    }
    return Container(child: content(_signupBloc, context, _countries));
    },
    );
    }
    }

    class Person {
    String email = '';
    String country = '';
    String countryCode = '';
    String phoneNumber = '';
    String firstname = '';
    String lastname = '';
    String password = '';
    bool termsAndCondition = false;
    }

    class CountryModel {
    String country = '';
    String countryCode = '';

    CountryModel({
    this.country,
    this.countryCode,
    });
    }

    最佳答案

    首先,如果您正在使用Bloc模式,则不能使用setState。另一件事是您应该为集团创建一个新的类(class)。您的情况是RegistrationBloc。然后导入RxDart。

    class SignupBloc{

    String _nameValue;

    BehaviourSubject<String> _nameSubject = BehaviourSubject<String>();
    Stream<String> get nameStream => _nameSubject.stream;
    StreamController<String> _name = StreamController<String>();
    Sink<String> get nameSink => _name.sink;

    SignupBloc(){

    //Inside the StreamController you can do anything to your value
    _name.stream.listen((name){
    if(name == "" || name == null){
    _nameSubject.addError("Please Enter Your Name");
    }else{
    _nameValue = name;
    }
    }
    }

    确保您首先创建和Bloc实例
    SignUpBloc _signUpBloc = SignInBloc();

    您的文本字段应该是这样的
    StreamBuilder<String>(
    stream: _signUpBloc.nameStream,
    builder: (context, snapshot) {
    return TextField(
    onChanged: (value) => _signUpBloc.nameSink.add(value),
    decoration: InputDecoration(
    labelText: "label", errorText: snapshot.error),
    );
    }
    );

    关于flutter - 如何在Flutter中使用Bloc模式处理用户注册错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57967391/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com