vessel_bloc 3.2.0 copy "vessel_bloc: ^3.2.0" to clipboard
vessel_bloc: ^3.2.0 copied to clipboard

vessel wrapper for bloc package

vessel_flutter wrapper for bloc package

Setup #

Add BlocProviderAdapter to ProviderContainer.adapters:

void main() {
  final container = ProviderContainer(
    adapters: [BlocProviderAdapter()],
  );
  // ...
}

Usage #

Lets take a look at how to use BlocProvider to provide a CounterCubit to a CounterPage and react to state changes with BlocBuilder.

counter_cubit.dart #

final counterCubitProvider = BlocProvider<CounterCubit, int>((_) => CounterCubit());

class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);
  void increment() => emit(state + 1);
  void decrement() => emit(state - 1);
}

main.dart #

void main() => runApp(
    // For widgets to be able to read providers, we need to wrap the entire
    // application in a "ProviderScope.root" widget.
    ProviderScope(
        child: CounterApp(),
    ),
);
class CounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterPage(),
    );
  }
}

counter_page.dart #

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Counter')),
      body: counterCubitProvider.builder(
        builder: (context, count) => Center(child: Text('$count')),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            child: const Icon(Icons.add),
            onPressed: () => counterCubitProvider.of(context).increment(),
          ),
          const SizedBox(height: 4),
          FloatingActionButton(
            child: const Icon(Icons.remove),
            onPressed: () => counterCubitProvider.of(context).decrement(),
          ),
        ],
      ),
    );
  }
}

Listen for changes #

final counterCubitProvider = BlocProvider<CounterCubit, int>(
    (_) => CounterCubit(),
);

...

Widget build(BuildContext context) {
    return counterCubitProvider.listener(
        listener: (context, state) {
            print("Counter: $state")
        },
        child: Text(...),
    );
}

Several listeners: #

Widget build(BuildContext context) {
    return MultiBlocListener(
        listeners: [
            counterCubitProvider.listener(
                listener: (context, state) {
                    print("Counter: $state");
                },
            ),
            themeCubitProvider.listener(
                listener: (context, state) {
                    print("Theme: $state");
                },
            ),
        ],
        child: Text(...),
    );
}

Filter states #

If we want to trigger listener only when counter's state is even:

counterCubitProvider.listener(
    listenWhen: (previousState, currentState) => currentState % 2 == 0,
    listener: (context, state) {
        print("Counter: $state");
    },
),

Consumer - combine builder and listener into single widget #

counterCubitProvider.consumer(
    listenWhen: (previousState, currentState) => currentState % 2 == 0,
    listener: (context, state) {
        print("Counter: $state")
    },
    buildWhen: (_, currentState) => currentState % 2 != 0,
    builder: (context, state) => Text("Only odd count: $state"),
);

Selector #

selector is analogous to builder but allows developers to filter updates by selecting a new value based on the current bloc state. Unnecessary builds are prevented if the selected value does not change. The selected value must be immutable in order for selector to accurately determine whether builder should be called again.

counterCubitProvider.selector<bool>(
    selector: (context, state) => state % 2 == 0,
    builder: (context, state) => Text("isEven: $state"),
);

Widgets #

Every provider's method has it's Widget counterpart:

  • .builder -> BlocBuilder<Bloc, State>
  • .listener -> BlocListener<Bloc, State>
  • .consumer -> BlocConsumer<Bloc, State>
  • .selector<SelectedState> -> BlocSelector<Bloc, State, SelectedState>

which are more suitable, if you want to define your bloc outside of vessel

Example

class _MyAppState extends State<MyApp> {
  final bloc = MyBloc();

  void dispose() {
    bloc.close();
    super.dispose();
  }

  Widget build(BuildContext context) => BlocBuilder<MyBloc, MyState>(
    bloc: bloc,
    builder: (context, state) => ... // build widget tree based on state
  );
}

How to define Repositories? #

You could use vessel's Provider for that:

final userRepositoryProvider = Provider((_) => UserRepository());

final userProfileCubitProvider = BlocProvider.factory<UserProfileCubit, User, int>(
    (read, int userId) => UserProfileCubit(
        userId: userId,
        repository: read(userRepositoryProvider),
    ),
);

// ...

Widget builder(BuildContext context) {
    return userProfileCubitProvider(1).builder(
        builder: (context, state) => Text("username: ${state.name}"),
    );
} 

How to scope, dispose and override cubits? #

Check out vessel_flutter documentation

Credits #

Credits to Felix Angelov for creating such an amazing package. Also, I've taken several documentation pieces from flutter_bloc

0
likes
140
pub points
0%
popularity

Publisher

unverified uploader

vessel wrapper for bloc package

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

bloc, flutter, flutter_bloc, meta, nested, vessel_flutter

More

Packages that depend on vessel_bloc