lang/dart

Flutter BLoC, Scoped Instances

C/H 2020. 9. 16. 08:30

Flutter BLoC, inheritedWidget Provider

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'; // Different Code of "Single Global Instance"

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of(context); // Different Code of "Single Global Instance"

    return Container(
      margin: EdgeInsets.all(8.0),
      child: Form(child: 
        Column(children: <Widget>[
          fieldEmail(bloc), // Different Code of "Single Global Instance"
          fieldPassword(bloc), // Different Code of "Single Global Instance"
          _submit(),
          ],
        ),
      ),
    );
  }

  Widget fieldEmail(Bloc bloc) { // Different Code of "Single Global Instance"
    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) { // Different Code of "Single Global Instance"
    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() {
    return RaisedButton(
      color: Colors.blue,
      child: Text('Submit', style: TextStyle(color: Colors.white),),
      onPressed: (){
        print('onPressed Submit');
      },
    );
  }
}

src/blocs/bloc.dart

import 'dart:async';
import 'validators.dart';

class Bloc extends Object with Validators {
  final _email = StreamController<String>();
  final _passwd = StreamController<String>();

  Stream<String> get email => _email.stream.transform(validatorEmail);
  Stream<String> get password => _passwd.stream.transform(validatorPassword);

  Function(String) get changeEmail => _email.sink.add;
  Function(String) get changePassword => _passwd.sink.add;

  dispose() {
    _email.close();
    _passwd.close();
  }
}

// Different Code of "Single Global Instance"
// final bloc = Bloc();

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;
  /*{
    // TODO: implement updateShouldNotify
    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 BLoC, RxDart combineLatestStream BehaviorSubject On Submit  (0) 2020.09.18
Flutter BLoC, RxDart combineLatestStream  (0) 2020.09.17
Flutter BLoC, Single Global Instance  (0) 2020.09.15
Flutter BLoC  (0) 2020.09.14
Dart BLoC Pattern  (0) 2020.09.11