BlocProvider.value Vs BlocProvider(create:)

18.8k Views Asked by At

i am using flutter_bloc, and i am wondering which method should i use and what is the difference between these two ways?: i read that the first one with (value) the bloc will not automatically closed, but actually i don't understand what is mean?

BlocProvider<LoginBloc>.value(
  value:  (LoginBloc(LoginInitialState(), AuthRepository())),
  ),

  

 BlocProvider<ProfileBloc>(
         create:  (context) => ProfileBloc(ProfileInitialState(), AuthRepository()),
       ),
7

There are 7 best solutions below

4
On BEST ANSWER

As far as I understand it, you would use:

BlocProvider.value(
  value: BlocProvider.of<BlocA>(context),
  child: ScreenA(),
);

when you have already created a bloc in a different BlocProvider and you just want that same bloc to be available somewhere else in the widget tree.

I'm assuming that because this bloc wasn't created by the BlocProvider you're currently using (with BlocProvider.value) it won't handle closing the bloc - that will be done by the original BlocProvider.

So unless the bloc that you want to use doesn't exist somewhere else already, you can probably just use the normal method with create.

0
On

I am wondering which method should i use and what is the difference between these two ways?

You should use BlocProvider(create:) unless you don't need to pick and use an already existing Bloc instance.

From package:flutter_bloc/src/bloc_provider.dart:

A new [Bloc] or [Cubit] should not be created in BlocProvider.value. New instances should always be created using the default constructor within the [Create] function.

The following code is wrong, because you create the LoginBloc instance in the value:

BlocProvider<LoginBloc>.value(
  value:  (LoginBloc(LoginInitialState(), AuthRepository())),
  child: .....
  ),

but you can use this to get the LoginBloc instance from elsewhere up the context tree:

BlocProvider<LoginBloc>.value(
  value:  BlocProvider.of<LoginBloc>(context),
  child: ....
  ),
0
On

based on the official docs, BlocProvider should be used to create new blocs which will be made available to the rest of the subtree. In this case, since BlocProvider is responsible for creating the bloc, it will automatically handle closing it.

BlocProvider(
  create: (BuildContext context) => BlocA(),
  child: ChildA(),
);

In some cases, BlocProvider can be used to provide an existing bloc to a new portion of the widget tree. This will be most commonly used when an existing bloc needs to be made available to a new route. In this case, BlocProvider will not automatically close the bloc since it did not create it.

BlocProvider.value(
  value: BlocProvider.of<BlocA>(context),
  child: ScreenA(),
);

so you did the first method in the wrong way.

0
On

In our case, if we're creating a brand new cubit just to pass into the child, we'll use:

BlocProvider<NameOfCubit>(
  ...
  child: Screen(),
)

and if we want to use a cubit we've already created then we'll pass it though with:

BlocProvider<NameOfCubit>.value(
  ...
  child: Screen(),
)
0
On

In my opinion, bloc provider will reset all your states and events, and send a new EventIntial again. on the other hand, Bloc.value won't send EventInitial again.

0
On

Here are scenarios that help illustrate the distinction between using both.

Screen one where the BlocProvider is created using the BlocProvider(create:)

BlocProvider(
      create: (context) => CounterBloc(),
      child: Scaffold(
        body: ...,
        floatingActionButton: FloatingActionButton(
          onPressed: _openFilterSchedule,
          child: Icon(Icons.filter_list),
        ),
      ),
    );

Open the bottomsheet where the BlocProvider.value is used

void _openFilterSchedule() {
  showModalBottomSheet<void>(
    context: context,
    builder: (BuildContext context) {
      // Using BlocProvider.value to share existing state
      return BlocProvider<CounterBloc>.value(
        value: context.read<CounterBloc>(),
        child: TheBottomSheet(),
      );
    },
  );
}

In this example, with BlocProvider.value, you're use the existing instance of CounterBloc created in the parent widget. It ensures shared state between the main screen and the bottom sheet.

2
On

BlocProvider.value() won't close your bloc automatically and you need to close it manually by using dispose method.