需要帮助了解 flutter_bloc 如何注入 bloc
Posted
技术标签:
【中文标题】需要帮助了解 flutter_bloc 如何注入 bloc【英文标题】:Need help understanding how flutter_bloc injects bloc 【发布时间】:2020-10-20 02:54:15 【问题描述】:据我目前了解,在 runApp 方法级别提供一个 bloc 使其在所有应用程序中都可用。我错了吗?
我有这个实现
我的 main.dart 文件
void main() => runApp(
RepositoryProvider<AuthenticationRepository>(
create: (context)
return AuthenticationService();
,
child: MultiBlocProvider(
providers: [
BlocProvider<AuthenticationBloc>(
create: (context)
final authService =
RepositoryProvider.of<AuthenticationRepository>(context);
return AuthenticationBloc(authService)..add(AppLoaded());
,
),
BlocProvider<SignupBloc>(
create: (context)
final authService =
RepositoryProvider.of<AuthenticationRepository>(context);
return SignupBloc(authService);
,
)
],
child: MyApp(),
),
),
);
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state)
if (state is AuthenticationSuccess)
return MainScreen(user: state.user);
return LoginScreen();
,
),
);
然后我有了这个小部件:
import 'dart:developer';
import 'package:myapp/features/signup/bloc/signup_bloc.dart';
import 'package:myapp/shared/ui/textStyles.dart';
import 'package:myapp/shared/ui/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
class ProfileInfoForm extends StatefulWidget
@override
_ProfileInfoFormState createState() => _ProfileInfoFormState();
class _ProfileInfoFormState extends State<ProfileInfoForm>
String _firstname, _lastname, _city, _country, _gender = "";
GlobalKey<FormState> _key = GlobalKey<FormState>();
List<bool> _selections = List.generate(2, (index) => false);
@override
Widget build(BuildContext context)
final _signupBloc = Provider.of<SignupBloc>(context);
return BlocListener<SignupBloc, SignupState>(
listener: (context, state)
if (state is CreateAccountFailure)
log("message");
,
child: BlocBuilder(
builder: (context, state)
if (state is CreateAccountLoading)
return CircularProgressIndicator();
return SingleChildScrollView(
child: Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Form(
key: _key,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 250,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: CustomTextField(
hintText: "Firstname",
secured: false,
onSave: (value)
setState(()
_firstname = value;
);
,
onValidate: (value)
if (value == "")
return "Please enter your firstname";
,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: CustomTextField(
hintText: "Lastname",
secured: false,
onSave: (value)
setState(()
_lastname = value;
);
,
onValidate: (value)
if (value == "")
return "Please enter your lastname";
,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: Text(
"Select your gender",
style: blackSubTitle,
),
),
ToggleButtons(
fillColor: Colors.white,
renderBorder: true,
color: Colors.black,
selectedBorderColor: Colors.redAccent,
borderRadius: BorderRadius.circular(20),
children: [
Container(
alignment: Alignment.center,
// decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)),
width: ScreenUtil().setWidth(220),
child: Text(
"Female",
style: blackSubTitle,
),
),
Container(
alignment: Alignment.center,
width: ScreenUtil().setWidth(220),
child: Text(
"Male",
style: blackSubTitle,
),
),
],
isSelected: _selections,
onPressed: (index)
setState(()
_selections =
List.generate(2, (index) => false);
_selections[index] = !_selections[index];
if (_selections.elementAt(0) == true)
setState(()
_gender = "Female";
);
if (_selections.elementAt(1) == true)
setState(()
_gender = "Male";
);
);
,
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FlatButton(
onPressed: ()
if (_key.currentState.validate())
_key.currentState.save();
// _signupBloc.add(
// InitProfilePressed(
// firstname: _firstname,
// lastname: _lastname,
// gender: _gender),
// );
else
,
child: Row(
children: [
Expanded(
child: Container(
alignment: Alignment.center,
width: 200,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black,
),
child: Text(
"Continue",
style: whiteSubTitle,
),
),
),
],
),
),
)
],
),
),
),
),
),
);
,
),
);
很遗憾,我收到了这个错误:
BlocProvider.of() called with a context that does not contain a Bloc of type Bloc<dynamic, dynamic>. No ancestor could be found starting from the context that was passed to BlocProvider.of<Bloc<dynamic, dynamic>>(). This can happen if the context you used comes from a widget above the BlocProvider. The context used was: BlocBuilder<Bloc<dynamic, dynamic>, dynamic>(dirty, state: _BlocBuilderBaseState<Bloc<dynamic, dynamic>,
动态>#a73f5(生命周期状态:创建))
BlocProvider.of
>()。 如果您使用的上下文来自 BlocProvider 上方的小部件,则可能会发生这种情况。 使用的上下文是:BlocBuilder , dynamic>(dirty, state: _BlocBuilderBaseState , dynamic>#a73f5(lifecycle state: created)) 相关的导致错误的小部件是: BlocListener #23 ComponentElement.performRebuild package:flutter/…/widgets/framework.dart:4571 #24 StatefulElement.performRebuild package:flutter/…/widgets/framework.dart:4719 #25 Element.rebuild 包:flutter/…/widgets/framework.dart:4262 #26 BuildOwner.buildScope 包:flutter/…/widgets/framework.dart:2667 #27 WidgetsBinding.drawFrame 包:flutter/…/widgets/binding.dart:866 #28 RendererBinding._handlePersistentFrameCallback 包:flutter/…/rendering/binding.dart:286 #29 SchedulerBinding._invokeFrameCallback 包:flutter/…/scheduler/binding.dart:1115 #30 SchedulerBinding.handleDrawFrame 包:flutter/…/scheduler/binding.dart:1054 #31 SchedulerBinding._handleDrawFrame 包:flutter/…/scheduler/binding.dart:970 #35 _invoke (dart:ui/hooks.dart:269:10) #36 _drawFrame (dart:ui/hooks.dart:227:3)(从 dart:async 中删除 3 帧)
我错过了什么?
谢谢你的帮助
【问题讨论】:
【参考方案1】:除了一件事,你做的都很好
您错过了 BlocBuilder 的类型
child: BlocBuilder<SignupBloc, SignupState>(
您还可以使用 BlocConsumer
,其中包括 BlocListener
和 BlocBuilder
功能
return BlocConsumer<SignupBloc, SignupState>(
listener: (context, state)
if (state is CreateAccountFailure)
log("message");
,
builder: (context, state)
if (state is CreateAccountLoading)
return CircularProgressIndicator();
【讨论】:
以上是关于需要帮助了解 flutter_bloc 如何注入 bloc的主要内容,如果未能解决你的问题,请参考以下文章