ig-dev
ig-dev

Reputation: 529

Unable to factor out list of `providers` from `MultiBlocProvider`

I want to combine BlocProviders from multiple sources into a single MultiBlocProvider. But any attempt to construct a List of BlocProviders outside of the MultiBlocProvider constructor arguments leads to a runtime error, that the Provider<XYZ> could not be found.

Error: Could not find the correct Provider<Foo> above this BlocListener<Foo, FooState> Widget

Say I have

return MultiBlocProvider(
  providers: [
    BlocProvider(create: (context) => FooCubit()),
    BlocProvider(create: (context) => BarCubit()),
  ],
  child: child,
);

That works. But I want

final concatenatedProviders = [
  BlocProvider(create: (context) => FooCubit()),
] + [
  BlocProvider(create: (context) => BarCubit()),
];
return MultiBlocProvider(
  providers: concatenatedProviders,
  child: child,
);

That does not work. Factoring out the providers does not work even if it is a single (non-concatenated) list.

How can I factor out the providers this so that they will still be found? I have tried several type annotations for the providers, such as List<BlocProvider<StateStreamableSource<Object?>>>, List<BlocProvider<dynamic>>, etc, but I couldn't find a working solution.

Upvotes: 0

Views: 698

Answers (1)

Rahul
Rahul

Reputation: 4341

Try this,

final providers = <BlocProvider>[
      BlocProvider<FooCubit>(create: (_) => FooCubit()),
    ] +
    <BlocProvider>[
      BlocProvider<BarCubit>(create: (_) => BarCubit()),
    ];

Full working example:

//foo_cubit.dart

import 'package:flutter_bloc/flutter_bloc.dart';

class FooCubit extends Cubit<int> {
  FooCubit() : super(0);

  void add(int x) {
    emit(state + x);
  }

  void substract(int x) {
    emit(state - x);
  }

  void multiply(int x) {
    emit(state * x);
  }

  void divide(int x) {
    emit(state ~/ x);
  }
}


//bar_cubit.dart
import 'package:flutter_bloc/flutter_bloc.dart';

class BarCubit extends Cubit<String> {
  BarCubit() : super("");

  void append(String str) {
    emit(state + str);
  }

  void reverse() {
    emit(String.fromCharCodes(state.codeUnits.reversed));
  }

  void clear() {
    emit('');
  }
}

 //main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:temp_bloc_runtime/bar_cubit.dart';
import 'package:temp_bloc_runtime/foo_cubit.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final providers = <BlocProvider>[
          BlocProvider<FooCubit>(create: (_) => FooCubit()),
        ] +
        <BlocProvider>[
          BlocProvider<BarCubit>(create: (_) => BarCubit()),
        ];

    return MultiBlocProvider(
      providers: providers,
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const MyHomePage(title: 'Flutter Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            BlocBuilder<FooCubit, int>(
              builder: (_, state) => Text(
                state.toString(),
              ),
            ),
            BlocBuilder<BarCubit, String>(
              builder: (_, state) => Text(
                state,
              ),
            ),
            const Expanded(child: SizedBox.shrink()),
            Row(
              children: [
                MaterialButton(
                  onPressed: () => context.read<FooCubit>().add(1),
                  child: const Text('+'),
                ),
                MaterialButton(
                  onPressed: () => context.read<FooCubit>().substract(1),
                  child: const Text('-'),
                ),
                MaterialButton(
                  onPressed: () => context.read<BarCubit>().append('A'),
                  child: const Text('+A'),
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}

Upvotes: 1

Related Questions