ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flutter BLoC, RxDart combineLatestStream
    lang/dart 2020. 9. 17. 08:30

    Flutter BLoC, RxDart SubmitedcombineLatestStream

    RxDart / ReactiveX

    • ReactiveX 라이브러리 제품군 제외.
    • 스트림 작업을위한 도우미 "객체 / 함수"있음
    • 각 버전은 유사하며 때로는 약간의 차이가 있습니다.
    • ReactiveX는 언어간에 유사해야하기 때문에 Dart가 사용하는 용어와 다른 용어를 사용합니다.

    Observable.combineLatest2, CombineLatestStream
    Obserable, Subject, CombineLatestStream
    https://rxmarbles.com/#combineLatest

    pubspec.yaml

    # ...
    
    dependencies:
      flutter:
        sdk: flutter
    
    
      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^0.1.3
    
      rxdart: ^0.24.1
      #rxdar: ^0.16.7
    
    #...

    main.dart

    import 'package:flutter/material.dart';
    import 'src/app.dart';
    
    void main() => runApp(App());

    src/app.dart

    import 'package:flutter/material.dart';
    import 'screens/login_screen.dart';
    import 'blocs/provider.dart';
    
    class App extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Provider(
          child: MaterialApp(
            title: 'Login',
            home: Scaffold(
              appBar: AppBar(
                title: Text('LoginForm'),
              ),
              body: LoginScreen(),
            ),
          ),
        );
      }
    }

    src/screens/login_screen.dart

    import 'package:flutter/material.dart';
    import '../blocs/bloc.dart';
    import '../blocs/provider.dart';
    
    class LoginScreen extends StatefulWidget {
      @override
      _LoginScreenState createState() => _LoginScreenState();
    }
    
    class _LoginScreenState extends State<LoginScreen> {
    
      @override
      Widget build(BuildContext context) {
        final bloc = Provider.of(context);
    
        return Container(
          margin: EdgeInsets.all(8.0),
          child: Form(child: 
            Column(children: <Widget>[
              fieldEmail(bloc),
              fieldPassword(bloc),
              _submit(bloc),
              ],
            ),
          ),
        );
      }
    
      Widget fieldEmail(Bloc bloc) {
        return StreamBuilder(
          stream: bloc.email,
          builder: (context, snapshot) {
            return TextField(
              onChanged: bloc.changeEmail,
              keyboardType: TextInputType.emailAddress,
              decoration: InputDecoration(
                labelText: 'Email',
                hintText: 'useanem@domain.com',
                errorText: snapshot.error,
              ),
            );
          }
        );
      }
    
      Widget fieldPassword(Bloc bloc) {
        return StreamBuilder(
          stream: bloc.password,
          builder: (context, snapshot) {
            return TextField(
              onChanged: bloc.changePassword,
              obscureText: true,
              decoration: InputDecoration(
                labelText: 'Password',
                hintText: 'over 3 charactor',
                errorText: snapshot.error,
              ),
            );
          }
        );
      }
    
      Widget _submit(Bloc bloc) {
        return StreamBuilder(
          stream: bloc.submitValid,
          builder: (context, snapshot) {
            return RaisedButton(
              color: Colors.blue,
              child: Text('Submit', style: TextStyle(color: Colors.white),),
              // AsyncSnapshot <T> Class
              // https://api.flutter.dev/flutter/widgets/AsyncSnapshot-class.html
              onPressed: snapshot.hasError
                ? null 
                : (){
                print('onPressed Submit');
              },
            );
          }
        );
      }
    }

    src/blocs/bloc.dart

    import 'dart:async';
    import 'package:flutter/foundation.dart';
    
    import 'validators.dart';
    import 'package:rxdart/rxdart.dart';
    
    class Bloc extends Object with Validators {
      final _email = StreamController<String>.broadcast();
      final _passwd = StreamController<String>.broadcast();
    
      Stream<String> get email => _email.stream.transform(validatorEmail);
      Stream<String> get password => _passwd.stream.transform(validatorPassword);
      // https://pub.dev/documentation/rxdart/latest/rx/CombineLatestStream-class.html
      // https://pub.dev/documentation/rxdart/latest/rx/CombineLatestStream/combine2.html
      // Stream<bool> get submitValid => Observable.combineLatest2(email, password, (e, p)=>true);
      Stream<bool> get submitValid => CombineLatestStream([email, password], (_)=>true);
    
      Function(String) get changeEmail => _email.sink.add;
      Function(String) get changePassword => _passwd.sink.add;
    
      dispose() {
        _email.close();
        _passwd.close();
      }
    }

    src/blocs/provider.dart

    import 'package:flutter/material.dart';
    import 'bloc.dart';
    
    class Provider extends InheritedWidget {
      final bloc = Bloc();
    
      Provider({key, Widget child}) : super(key: key, child: child);
    
      // @override
      // bool updateShuldNotify(_) => true;
      @override
      bool updateShouldNotify(InheritedWidget oldWidget) => true;
      /*{
        throw UnimplementedError();
      }*/
    
      static Bloc of(BuildContext context) {
        // ignore: deprecated_member_use
        // return (context.inheritFromWidgetOfExactType(Provider) as Provider).bloc;
        // https://stackoverflow.com/a/59304297
        return (context.dependOnInheritedWidgetOfExactType<Provider>()).bloc;
    
      }
    }

    src/blocs/validators.dart

    import 'dart:async';
    
    class Validators {
      final validatorEmail = StreamTransformer<String, String>.fromHandlers(
        handleData: (String email, sink) {
          if( email.contains('@') ){
            sink.add(email);
          } else {
            sink.addError('Enter a valid email');
          }
        }
      );
    
      final validatorPassword = StreamTransformer<String, String>.fromHandlers(
        handleData: (String passwd, sink) {
          if( passwd.length >= 3 ) {
            sink.add(passwd);
          } else {
            sink.addError('password must be at leat 3 characters');
          }
        }
      );
    }

    Flutter State

    'lang > dart' 카테고리의 다른 글

    Flutter Animation  (0) 2020.09.21
    Flutter BLoC, RxDart combineLatestStream BehaviorSubject On Submit  (0) 2020.09.18
    Flutter BLoC, RxDart combineLatestStream  (0) 2020.09.17
    Flutter BLoC, Scoped Instances  (0) 2020.09.16
    Flutter BLoC, Single Global Instance  (0) 2020.09.15
    Flutter BLoC  (0) 2020.09.14

    댓글 0

Designed by Tistory.