skip to Main Content

How can I prevent the bloc disposing?
And when and where I want it to be disposed?

When the state does not change, but the value that comes with that state, such as a list, when it changes, ui does not notice the change of the value with the state. The state must be changed so that the ui understands. How can I handle this?

2

Answers


  1. Bloc (Business Logic Component) packages like flutter_bloc and bloc in Flutter give you a means to control your application’s state and inform the UI of changes. The lifecycle and scope of the widget that uses a Bloc determine whether or not it should be disposed of.

    Here are some considerations for disposing of a Bloc:

    1. Scoped to Widget’s Lifecycle: You should normally use the BlocProvider or BlocListener from the flutter_bloc package if you wish to get rid of a Bloc when a widget is removed from the widget tree (for example, when a page is popped in a navigation stack). When the widget is removed from the widget tree, these widgets automatically take care of disposing of the Bloc.

       BlocProvider(
         create: (context) => DesiredBloc(),
         child: DesiredWidget(),
       )
      
    2. Global Scope: You might not want to get rid of a Bloc if it needs to last for the duration of the application’s lifespan. In this situation, you can handle the Bloc in your app at a higher level, such in the main function, and keep it active for the duration that your app is in use.

    3. Manual Disposal: In the widget’s discard method, you can manually dispose of a Bloc if you need more precise control over when it is disposed. For instance:

       class YourWidget extends StatefulWidget {
         @override
         _YourWidgetState createState() => _YourWidgetState();
       }
      
       class _YourWidgetState extends State<YourWidget> {
         final YourBloc _yourBloc = YourBloc();
      
         @override
         void dispose() {
           _yourBloc.close();
           super.dispose();
         }
      
         @override
         Widget build(BuildContext context) {
           return BlocProvider(
             create: (context) => _yourBloc,
             child: YourChildWidget(),
           );
         }
       }
      

    Regarding your second query, you can solve this by using Equatable or comparable approaches to make sure that the state object is treated differently when the value changes even while the state itself does not.

    1. Using Equatable: You can override the props function in your state class to compare the values inside the state by extending Equatable. In this manner, because the state object is seen as different when the value changes, it will cause a UI update.

       class YourState extends Equatable {
         final List<int> data;
      
         YourState(this.data);
      
         @override
         List<Object?> get props => [data];
       }
      
    2. Clone State: In some circumstances, cloning the state may be necessary to force a UI update. For instance:

       void updateData(List<int> newData) {
         final currentState = state;
         final newState = YourState([...currentState.data, ...newData]);
         emit(newState);
       }
      

    Even though the state object reference stays the same, you can cause a UI update by creating a new state object with the modified values and emitting it.

    Remember that the Flutter framework is made to render pages more efficiently when the state remains static, therefore forcing updates should only be done sparingly to prevent needless UI re-rendering.

    Login or Signup to reply.
  2. BlocBuilders and BlocListeners are notified just if a new state is emitted. So, to handle that situation, normally, I choose one of below approaches:

    1. emit a new state with the list changed (making a copy of the list if state is a Equatable);
    2. emit a state using different status like this to force UI changes:
    emit(
     state.copyWith(
       list: items,
       status: StateStatus.loaded,
     ),
    );
    //...
    
    emit(
     state.copyWith(
       status: StateStatus.loadingMoreItems,
     ),
    );
    items.addAll(newItems);
    
    emit(
     state.copyWith(
       status: StateStatus.loaded,
     ),
    );
    

    Disponsing BLoCs are another part of it and the recommended is to let BlocProvider handle the task alone or to call bloc.close() on State.dispose() method.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search