Flutter - ошибка потока не сохраняется (используется шаблон blo c) - PullRequest
0 голосов
/ 20 февраля 2020

Итак, я пытаюсь создать форму регистрации во флаттере, используя потоки и шаблон blo c.

Проблема в том, что ошибка, добавленная в приемник для одного из моих потоков, кажется, не сохраняется?

Кажется, что метод submitValid не учитывает ошибку, добавленную в поток паролей, поэтому кнопка входа в систему может быть нажата, когда она не должна

Шаги для воспроизведения:

  • Заполните действующий адрес электронной почты

  • Заполните действительный пароль (поле пароля)

  • Заполните действительный пароль (поле для повторного ввода пароля)

  • Удалить все из поля для повторного ввода

  • Удалить все из поля для ввода пароля.

  • Введите действительный пароль в поле пароля, и кнопка входа в систему будет активна, даже если поле повторного ввода пусто.

Вот мой код вместе со скриншотом.

Blo c .dart

import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';

import 'validators.dart';
import 'dart:io';
import 'package:rxdart/rxdart.dart';

class Bloc extends Object with Validators {

  final _email = BehaviorSubject<String>();
  final _password = BehaviorSubject<String>();
  final _passwordretype = BehaviorSubject<String>();
  final _isSignedIn = BehaviorSubject<bool>();

  //Add data to stream
  Stream<String> get email => _email.stream.transform(validateEmail);
  Stream<String> get password => _password.stream.transform(validatePassword);

  Stream<String> get passwordretype=> _passwordretype.stream.transform(validatePasswordRetype)
  .doOnData((String c){
    if(0 != _password.value.compareTo(c)){
      _passwordretype.addError("Passwords do not match");
    }
  });

  Stream<bool> get signInStatus => _isSignedIn.stream;

  Stream<bool> get submitValid =>
    Rx.combineLatest3(email, password, passwordretype, (e, p, r) => true);


  //Change data
  Function(String) get changeEmail => _email.sink.add;
  Function(String) get changePassword => _password.sink.add;
  Function(String) get changePasswordRetype => _passwordretype.sink.add;
  Function(bool) get showProgressBar => _isSignedIn.add;

  register() async {

    final FirebaseAuth _auth = FirebaseAuth.instance;

    try {
      showProgressBar(true);
      final FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
        email: _email.value,
        password: _password.value,
      ))
          .user;
      if (user != null) {
//        setState(() {
//          _success = true;
//          _userEmail = user.email;
//          Navigator.of(context).pushNamedAndRemoveUntil(
//              '/home', (Route<dynamic> route) => false);
//
////        Navigator.of(context).pushReplacementNamed('/home');
//
//        });
      } else {
//        Scaffold.of(context).showSnackBar(SnackBar(
//          content: Text("Error occured, please try again later"),
//        ));
//        _success = false;
      }
    } catch (err) {
      _isSignedIn.addError(err);
      print(err);
//      setState(() {
//        _showLoading = false;
//        _error = true;
//      });
    }



  }



  dispose() {
    _email.drain();
    _email.close();
    _password.drain();
    _password.close();
    _passwordretype.drain();
    _passwordretype.close();
  }

}

RegistrationScreen.dart * 104 0 * import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:lendy/src/blocs/bloc.dart'; import 'package:lendy/src/blocs/provider.dart'; class SignupScreen extends StatelessWidget { // final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); // final TextEditingController _emailController = TextEditingController(); // final TextEditingController _passwordController = TextEditingController(); // final TextEditingController _passwordController2 = TextEditingController(); final FirebaseAuth _auth = FirebaseAuth.instance; // final GoogleSignIn _googleSignIn = GoogleSignIn(); String _userID = ""; bool _success; String _userEmail; @override Widget build(BuildContext context) { final bloc = Provider.of(context); return Scaffold( appBar: AppBar( title: Text("Signup"), ), body: Container( child: Column( children: <Widget>[ emailField(bloc), passwordField(bloc), passwordFieldRe(bloc), SizedBox( height: 10.0, ), button(bloc) ], ), ), ); } Widget emailField(Bloc bloc) { return StreamBuilder( stream: bloc.email, builder: (context, snapshot) { return TextField( onChanged: bloc.changeEmail, keyboardType: TextInputType.emailAddress, decoration: InputDecoration( hintText: 'Enter email address', labelText: 'Email-address', errorText: snapshot.error), ); }, ); } Widget passwordField(Bloc bloc) { return StreamBuilder( stream: bloc.password, builder: (context, snapshot) { return TextField( onChanged: bloc.changePassword, decoration: InputDecoration( hintText: 'Enter password', labelText: 'Password', errorText: snapshot.error), ); }); } Widget passwordFieldRe(Bloc bloc) { return StreamBuilder( stream: bloc.passwordretype, builder: (context, snapshot) { return TextField( onChanged: bloc.changePasswordRetype, decoration: InputDecoration( hintText: 'Retype password', labelText: 'Password', errorText: snapshot.error), ); }); } Widget button(Bloc bloc) { return StreamBuilder( stream: bloc.submitValid, builder: (context, snapshot) { return RaisedButton( child: Text('Register'), color: Colors.blue, //if true onPressed: snapshot.hasData ? () { // bloc.showProgressBar(true); bloc.register(); } : null); }, ); } Widget buttons(Bloc bloc) { return StreamBuilder( stream: bloc.submitValid, builder: (context, snapshot1) { return StreamBuilder( stream: bloc.signInStatus, builder: (context, snapshot2) { if (!snapshot2.hasData || snapshot2.hasError) { return Column( children: <Widget>[ RaisedButton( child: Text('Register'), color: Colors.blue, onPressed: snapshot1.hasData ? () { bloc.register(); } : null, ), snapshot2.hasError ? Text("ee") : Container() ], ); } else { return CircularProgressIndicator(); } }, ); }, ); } Widget submitButton(Bloc bloc) { return StreamBuilder( stream: bloc.signInStatus, builder: (context, snapshot) { if (snapshot.hasError || !snapshot.hasData) { return buttons(bloc); } else { return CircularProgressIndicator(); } }); } / Validators.dart

import 'dart:async';

class Validators {

  final validateEmail = StreamTransformer<String, String>.fromHandlers(
      handleData: (email, sink){
        if (RegExp(
        r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
        .hasMatch(email)){
          sink.add(email);
        } else {
          sink.addError('Please enter a valid email address.');
        }
      }
  );

  final validatePassword = StreamTransformer<String, String>.fromHandlers(
      handleData: (password, sink){
        if (password.length > 3){
          sink.add(password);
        } else {
          sink.addError('Password is too short.');
        }
      }
  );


  final validatePasswordRetype = StreamTransformer<String, String>.fromHandlers(
      handleData: (password, sink){
        print("HANDLE DATA");
        if (password.length > 3){
          sink.add(password);
        } else {
          sink.addError('Password is too short.');
        }
      }
  );


}

снимок экрана

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Для потока submitValid вы используете BehaviorSubjects вместо stream.transforms, поэтому ваш submitValid не получает ошибок. Замените ваш submitValid следующим кодом:

Stream<bool> get submitValid => Rx.combineLatest3(email, password, passwordretype, (e, p, r) => true);

0 голосов
/ 20 февраля 2020

Нашел похожую проблему здесь

Я изменил свою submitValid функцию следующим образом:

Stream<bool> get submitValid =>
    Rx.combineLatest3(email, password, passwordretype, (e, p, r) {
      if (p == _password.value && r == _passwordretype.value){
        return true;
      } else {
        return false;
      }
    });

И изменил onPressed в моем button Widget как так. Она отображает активируемую кнопку только в том случае, если снимок возвращает значение true.

  Widget button(Bloc bloc) {
    return StreamBuilder(
      stream: bloc.submitValid,
      builder: (context, snapshot) {
        return RaisedButton(
            child: Text('Register'),
            color: Colors.blue,
            onPressed: snapshot.hasData && snapshot.data
                ? () {
              bloc.register();
            }
                : null);
      },
    );
  }
...