Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Provider vs BLoC vs Redux

bkosarzycki
December 11, 2019

Provider vs BLoC vs Redux

In the following presentation I compare main Flutter architecture patterns - package:provider, BLoC and Redux.

Source: https://github.com/kosiara/bloc-vs-pprov-vs-redux

Different architecture have their advantages & disadvantages. Simplest application can take advantage of a stateful widget + inherited widget - which solves the problem of reference passing.

BLoC is more complicated but definitely pays off when you're dealing with a bigger application.

Finally we have redux. This is the most robust example with most boilerplate code. There are non-deniable example of such an architecture:

- single source of truth which can be serialized and later on saved/restored from disk
- ease of logging actions
- clear data-flow
- ability to undo actions

bkosarzycki

December 11, 2019
Tweet

More Decks by bkosarzycki

Other Decks in Programming

Transcript

  1. Poznan Flutter Developer Group @override Widget build(BuildContext context) { return

    MultiProvider( providers: [ ChangeNotifierProvider(builder: (context) => UserLogin()), //hint: other providers go here ], child: Scaffold( appBar: AppBar( …. ) ) ); } class UserLogin with ChangeNotifier { String _user; …. } UserLogin userLogin = Provider.of<UserLogin>(context); userLogin.someAction(); userLogin.notifyListeners(); // usually inside another method
  2. Poznan Flutter Developer Group class UserSignInBloc { Sink<UserLogin> get login

    => _userCredentialsStream.sink; final _userCredentialsStream = BehaviorSubject<UserLogin>(); Stream<UserAuthenticationState> userSigned; UserSignInBloc() { userSigned = Observable.merge([ _userCredentialsStream.stream.switchMap(_signIn), // other login methods go here ]).asBroadcastStream(); } void dispose() { _userCredentialsStream.close(); } // Business logic here } _userSignInBloc.login.add(UserLogin(user, password));
  3. Poznan Flutter Developer Group var _userSignInBloc = UserSignInBloc(); ResultWidget(_userSignInBloc.userSigned), class

    ResultWidget extends StatefulWidget { Stream<UserAuthenticationState> userSigned; ResultWidget(this.userSigned); @override _ResultWidgetState createState() => _ResultWidgetState(userSigned); } class _ResultWidgetState extends State<ResultWidget> { var loginResultText = ""; _ResultWidgetState(Stream<UserAuthenticationState> userSigned){ userSigned.listen(onLoginDataChanged); } void onLoginDataChanged(UserAuthenticationState event) { if (event is UserAuthenticationLoading) { setState(() { loginResultText = "LOADING..."; }); } }
  4. Poznan Flutter Developer Group final store = Store<AppState>( appReducer, initialState:

    AppState.noLoggedUser(), middleware: createStoreLoginMiddleware(), ); @override Widget build(BuildContext context) { return StoreProvider( store: store, child: MaterialApp( … ) ); } UserLogin user = StoreProvider.of<AppState>(context).state.loggedUser; StoreProvider.of<AppState>(context).dispatch(LoginRequestAction(user, password)); class LoginUnsuccessfulAction {} TypedReducer<UserLogin, LoginSuccessfulAction>(_setUser) UserLogin _setUser(UserLogin user, LoginSuccessfulAction action) { print("Previous user: $user , storing new user: ${action.user}"); return action.user; }
  5. Poznan Flutter Developer Group Bartosz Kosarzycki Poznań Flutter Developer Group

    facebook.com/poznanflutter meetup.com/poznan-flutter-developers