Search code examples
flutterdartblocflutter-bloc

Bloc builder cannot detect the cubit provided


I'm creating a page named Products Page, and it has this structure :

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    return Padding(
      padding: const EdgeInsets.only(top: 60, left: 20, right: 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          _buildTextField(),
          const SizedBox(height: 60),
          _buildTitle(),
          const SizedBox(height: 10),
          _buildAddButton(),
          const SizedBox(height: 10),
          _buildProductsList(),
        ],
      ),
    );
  }

And the _buildAddButton() provides two widgets that uses two different instances of the same cubit:

Widget _buildAddButton() {
    return Column(
      children: [
        BlocProvider(
          create: (context) => di.sl<CsvFilePickerCubit>(),
          child: const ImportMedication(),
        ),
        const SizedBox(height: 10),
        BlocProvider(
          create: (context) => di.sl<CsvFilePickerCubit>(),
          child: const ImportParapharmaceutical(),
        ),
      ],
    );
  }

I'm using GetIt as a service locator, now the problem is when I put a BlocBuilder in the widgets it tells me that it cannot detect any provider.

Here is the code for the two widgets ImportMedication() and ImportParapharmaceutical():

class ImportMedication extends StatelessWidget {
  const ImportMedication({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocBuilder(
      builder: (context, state) {
        if (state is CsvFilePickerLoading) {
          return const Loading();
        } else {
          return CustomButton(
            title: 'Import medication CSV',
            onPressed: () {
              context
                  .read<CsvFilePickerCubit>()
                  .pickCSVFile(context, type: 'medication');
            },
          );
        }
      },
    );
  }
}

and the second one:

class ImportParapharmaceutical extends StatelessWidget {
  const ImportParapharmaceutical({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocBuilder(
      builder: (context, state) {
        if (state is CsvFilePickerLoading) {
          return const Loading();
        } else {
          return CustomButton(
            title: 'Import parapharmaceutical CSV',
            onPressed: () {
              context
                  .read<CsvFilePickerCubit>()
                  .pickCSVFile(context, type: 'parapharmaceutical');
            },
          );
        }
      },
    );
  }
}

And here is the CsvFilePickerCubit:

class CsvFilePickerCubit extends Cubit<CsvFilePickerState> {
  ProductsRepository repository;
  CsvFilePickerCubit(this.repository) : super(CsvFilePickerInitial());

  Future<void> pickCSVFile(BuildContext context, {required String type}) async {
    emit(CsvFilePickerLoading());

    try {
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.custom,
        allowedExtensions: ['csv', 'xlsx', 'xls'],
      );

      if (result != null) {
        String csvText = String.fromCharCodes(result.files.first.bytes!);
        List<List<dynamic>> csvList =
            const CsvToListConverter().convert(csvText);

        final failureOrUnit = await repository.importDataCSV(
          csvList: csvList,
          type: type,
        );

        failureOrUnit.fold(
          (failure) =>
              emit(CsvFilePickerError(mapFailureToMessage(failure, context))),
          (_) => emit(CsvFilePickerSuccess()),
        );
      }
    } catch (e) {
      emit(CsvFilePickerError(e.toString()));
    }
  }
}

Solution

  • You have to specify the type of cubit what you want to use in BlocBuilder.

    BlocBuilder<CsvFilePickerCubit, CsvFilePickerState>{}