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));
});
},
);
}
}
这就是我使用 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
并编译了代码。
我正在从一个已弃用的教程中学习 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));
});
},
);
}
}
这就是我使用 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
并编译了代码。