Search code examples
fluttermobilebloccubit

is Flutter bloc always must have one property(data)


I am worker for a project on flutter with bloc as state management.

But my screen contain a wide variety of data.

How can I management all this data?

class ProductCubit extends Cubit<ProductState> {
  Worker worker = Worker();
  List<ProductMakePriceChange> productsPriceChange = [];
  List<PurchaseCount> purchaseCount = [];
  int productCount = 0;
  int productSaleCount = 0;
  int productCategoryCount = 0;
  int productUnitCount = 0;
}

I have One state for each data (Loading state) And One method for each data to load it

The problem!

when one state are change, all screen are rebuild

I need to change just one partition from my screen, just that partition when that data are effect


Solution

  • There are several ways to achieve this.

    As you guessed correctly, you can of course move some fields to separate cubits. Another option would be to implement different subclasses of ProductState and check for the type in the BlocBuilder or BlocConsumer at runtime.

    class ProductCubit extends Cubit<ProductState> {
      ProductCubit()
          : super(
              const ProductInitial(
                ProductInfo(
                  productsPriceChange: [],
                  purchaseCount: [],
                  productSaleCount: 0,
                  productCategoryCount: 0,
                  productCount: 0,
                  productUnitCount: 0,
                ),
              ),
            );
    
      Future<void> loadProductPurchaseCount() async {
        emit(ProductPurchaseCountLoadInProgress(state.productInfo));
        try {
          // TODO load product purchase count
          final productPurchaseCount = <dynamic>[];
          emit(
            ProductPurchaseCountLoadSuccess(
              state.productInfo.copyWith(
                purchaseCount: productPurchaseCount,
              ),
            ),
          );
        } catch (_) {
          emit(
            ProductPurchaseCountLoadSuccess(state.productInfo),
          );
        }
      }
    }
    
    abstract class ProductState extends Equatable {
      const ProductState(this.productInfo);
    
      final ProductInfo productInfo;
    
      @override
      List<Object?> get props => [productInfo];
    }
    
    class ProductInitial extends ProductState {
      const ProductInitial(ProductInfo productInfo) : super(productInfo);
    }
    
    class ProductPurchaseCountLoadInProgress extends ProductState {
      const ProductPurchaseCountLoadInProgress(ProductInfo productInfo)
          : super(productInfo);
    }
    
    class ProductPurchaseCountLoadFailure extends ProductState {
      const ProductPurchaseCountLoadFailure(ProductInfo productInfo)
          : super(productInfo);
    }
    
    class ProductPurchaseCountLoadSuccess extends ProductState {
      const ProductPurchaseCountLoadSuccess(ProductInfo productInfo)
          : super(productInfo);
    }
    

    Last, but not least, there is a relatively new Widget called BlocSelector which lets you check the state in order to determine whether the child should be built.

    BlocSelector<BlocA, BlocAState, SelectedState>(
      selector: (state) {
        // return selected state based on the provided state.
      },
      builder: (context, state) {
        // return widget here based on the selected state.
      },
    )
    

    Check out the docs: https://pub.dev/packages/flutter_bloc