Dart:创建 bloc 时出错 - "Tried to read a provider that threw during the creation of its value. "

Dart: Error while creating bloc - "Tried to read a provider that threw during the creation of its value. "

我正在从一个已弃用的教程中学习 bloc,但我很难让它发挥作用。 我收到的错误是:

 Error while creating GetRandomNumberTrivia
(...)
The following StateError was thrown building InheritedProvider<NumberTriviaBloc>:
Bad state: Tried to read a provider that threw during the creation of its value.
The exception occurred during the creation of type NumberTriviaBloc.

完整错误:https://pastebin.com/CpvrFZ1v

这是我的 bloc 文件:

const String serverFailureMessage = 'Server failure';
const String cacheFailureMessage = 'Cache failure';
const String invalidInputMessage =
    'Invalid input, the number should be positive integer or zero';

class NumberTriviaBloc extends Bloc<NumberTriviaEvent, NumberTriviaState> {
  final GetConcreteNumberTrivia getConcreteNumberTrivia;
  final GetRandomNumberTrivia getRandomNumberTrivia;
  final InputConverter inputConverter;

  NumberTriviaBloc(
      {required this.getConcreteNumberTrivia,
      required this.getRandomNumberTrivia,
      required this.inputConverter})
      : super(Empty()) {

    on<GetTriviaForConcreteNumber>(
      (event, emit) async {
        final inputEither =
            inputConverter.stringToUnsignedInteger(event.numberString);
        inputEither.fold((l) =>  emit(Error(message: invalidInputMessage)),
            (r)  async {
          emit(Loading());
          final failureOrTrivia = await getConcreteNumberTrivia(Params( number: r));
          //todo message
          failureOrTrivia.fold((l) => emit(Error(message: 'problem message')),
              (r) => emit(Loaded(trivia: r)));
        });
      },
    );

    on<GetTriviaForRandomNumber>(
      (event, emit) async {
        emit(Loading());
        final failureOrTrivia = await getRandomNumberTrivia(NoParams());

        failureOrTrivia.fold((l) => emit(Error(message: "Invalid input")),
            (r) async {
          emit(Loaded(trivia: r));

        });
      },
    );
  }
}

这是我模仿的代码:https://github.com/ResoCoder/flutter-tdd-clean-architecture-course/blob/master/lib/features/number_trivia/presentation/bloc/number_trivia_bloc.dart

这就是我使用 BlocProvider 的方式:

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

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

BlocProvider<NumberTriviaBloc> buildBody(BuildContext context) {
  return BlocProvider(
    create: (_) =>  sl<NumberTriviaBloc>(),
    child: Center(
      child: Padding(
        padding: const EdgeInsets.all(10),
        child: Column(
          children: <Widget>[
            const SizedBox(height: 10),
             BlocBuilder<NumberTriviaBloc, NumberTriviaState>(
              builder: (context, state) {
                if (state is Empty) {
                  return const MessageDisplay(
                    message: 'Start searching!',
                  );
                } else if (state is Loading) {
                  return const LoadingWidget();
                } else if (state is Loaded) {
                  return TriviaDisplay(numberTrivia: state.trivia);
                } else if (state is Error) {
                  return MessageDisplay(
                    message: state.message);
                }else{
                  return Container();
                }
              },
            ),
            const TriviaControls(),
          ],
        ),
      ),
    ),
  );
}

这就是我使用依赖注入初始化 bloc 的方式:

import 'injection_container.dart' as di;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await di.init();
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
(...)
      home: const NumberTriviaPage(),
    );
  }
}
//sl = serviceLocator
final sl = GetIt.instance;

Future<void> init() async {
  //serviceLocator call looking for are registered types/dependencies
  sl.registerFactory(() => NumberTriviaBloc(getConcreteNumberTrivia: sl(), getRandomNumberTrivia: sl(), inputConverter: sl()));
(...)

}

根据错误,问题似乎出在 GetRandomNumberTrivia 的某个地方,但我以与类似 GetConcreteNumberTrivia 相同的方式实现它,我看不出这里有什么问题。

在 class GetRandomNumberTrivia 中,我为字段 repository 添加了键入 NumberTriviaRepository 并编译了代码。